blob: ec54865a5107d018dbe56cee27e02d3a275db343 [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
[email protected]9a9787ed2010-07-30 23:21:591346// Test the request-challenge-retry sequence for basic auth, over a connection
1347// that requires a restart when setting up an SSL tunnel.
1348TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1349 // Configure against proxy server "myproxy:70".
1350 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1351 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1352 session_deps.net_log = log.bound().net_log();
1353 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1354
1355 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1356
1357 HttpRequestInfo request;
1358 request.method = "GET";
1359 request.url = GURL("https://www.google.com/");
1360 // when the no authentication data flag is set.
1361 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1362
1363 // Since we have proxy, should try to establish tunnel.
1364 MockWrite data_writes1[] = {
1365 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1366 "Host: www.google.com\r\n"
1367 "Proxy-Connection: keep-alive\r\n\r\n"),
1368
1369 // After calling trans->RestartWithAuth(), this is the request we should
1370 // be issuing -- the final header line contains the credentials.
1371 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1372 "Host: www.google.com\r\n"
1373 "Proxy-Connection: keep-alive\r\n"
1374 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1375
1376 MockWrite("GET / HTTP/1.1\r\n"
1377 "Host: www.google.com\r\n"
1378 "Connection: keep-alive\r\n\r\n"),
1379 };
1380
1381 // The proxy responds to the connect with a 407, using a persistent
1382 // connection.
1383 MockRead data_reads1[] = {
1384 // No credentials.
1385 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1386 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1387 MockRead("Proxy-Connection: close\r\n\r\n"),
1388
1389 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1390
1391 MockRead("HTTP/1.1 200 OK\r\n"),
1392 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1393 MockRead("Content-Length: 100\r\n\r\n"),
1394 MockRead(false, OK),
1395 };
1396
1397 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1398 data_writes1, arraysize(data_writes1));
1399 session_deps.socket_factory.AddSocketDataProvider(&data1);
1400 SSLSocketDataProvider ssl(true, OK);
1401 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1402
1403 TestCompletionCallback callback1;
1404
1405 int rv = trans->Start(&request, &callback1, log.bound());
1406 EXPECT_EQ(ERR_IO_PENDING, rv);
1407
1408 rv = callback1.WaitForResult();
1409 EXPECT_EQ(OK, rv);
1410 size_t pos = ExpectLogContainsSomewhere(
1411 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1412 NetLog::PHASE_NONE);
1413 ExpectLogContainsSomewhere(
1414 log.entries(), pos,
1415 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1416 NetLog::PHASE_NONE);
1417
1418 const HttpResponseInfo* response = trans->GetResponseInfo();
1419 ASSERT_FALSE(response == NULL);
1420
1421 EXPECT_EQ(407, response->headers->response_code());
1422 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1423
1424 // The password prompt info should have been set in response->auth_challenge.
1425 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1426
1427 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1428 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1429 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1430
1431 TestCompletionCallback callback2;
1432
1433 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1434 EXPECT_EQ(ERR_IO_PENDING, rv);
1435
1436 rv = callback2.WaitForResult();
1437 EXPECT_EQ(OK, rv);
1438
1439 response = trans->GetResponseInfo();
1440 ASSERT_FALSE(response == NULL);
1441
1442 EXPECT_TRUE(response->headers->IsKeepAlive());
1443 EXPECT_EQ(200, response->headers->response_code());
1444 EXPECT_EQ(100, response->headers->GetContentLength());
1445 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1446
1447 // The password prompt info should not be set.
1448 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1449}
1450
[email protected]11203f012009-11-12 23:02:311451// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321452// proxy connection, when setting up an SSL tunnel.
1453TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1454 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591455 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541456 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1457 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321459
[email protected]5695b8c2009-09-30 21:36:431460 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321461
[email protected]1c773ea12009-04-28 19:58:421462 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321463 request.method = "GET";
1464 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461465 // Ensure that proxy authentication is attempted even
1466 // when the no authentication data flag is set.
1467 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321468
1469 // Since we have proxy, should try to establish tunnel.
1470 MockWrite data_writes1[] = {
1471 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451472 "Host: www.google.com\r\n"
1473 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321474
1475 // After calling trans->RestartWithAuth(), this is the request we should
1476 // be issuing -- the final header line contains the credentials.
1477 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1478 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451479 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321480 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1481 };
1482
1483 // The proxy responds to the connect with a 407, using a persistent
1484 // connection.
1485 MockRead data_reads1[] = {
1486 // No credentials.
1487 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1488 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1489 MockRead("Content-Length: 10\r\n\r\n"),
1490 MockRead("0123456789"),
1491
1492 // Wrong credentials (wrong password).
1493 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1494 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1495 MockRead("Content-Length: 10\r\n\r\n"),
1496 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421497 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321498 };
1499
[email protected]31a2bfe2010-02-09 08:03:391500 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1501 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591502 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321503
1504 TestCompletionCallback callback1;
1505
[email protected]dbb83db2010-05-11 18:13:391506 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421507 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321508
1509 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421510 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391511 size_t pos = ExpectLogContainsSomewhere(
1512 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1513 NetLog::PHASE_NONE);
1514 ExpectLogContainsSomewhere(
1515 log.entries(), pos,
1516 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1517 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321518
[email protected]1c773ea12009-04-28 19:58:421519 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321520 EXPECT_FALSE(response == NULL);
1521
1522 EXPECT_TRUE(response->headers->IsKeepAlive());
1523 EXPECT_EQ(407, response->headers->response_code());
1524 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421525 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321526
1527 // The password prompt info should have been set in response->auth_challenge.
1528 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1529
[email protected]71e4573a2009-05-21 22:03:001530 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321531 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1532 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1533
1534 TestCompletionCallback callback2;
1535
1536 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441537 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421538 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321539
1540 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421541 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321542
1543 response = trans->GetResponseInfo();
1544 EXPECT_FALSE(response == NULL);
1545
1546 EXPECT_TRUE(response->headers->IsKeepAlive());
1547 EXPECT_EQ(407, response->headers->response_code());
1548 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421549 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321550
1551 // The password prompt info should have been set in response->auth_challenge.
1552 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1553
[email protected]71e4573a2009-05-21 22:03:001554 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321555 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1556 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131557
[email protected]e60e47a2010-07-14 03:37:181558 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1559 // out of scope.
1560 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321561}
1562
[email protected]a8e9b162009-03-12 00:06:441563// Test that we don't read the response body when we fail to establish a tunnel,
1564// even if the user cancels the proxy's auth attempt.
1565TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1566 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591567 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441568
[email protected]e44de5d2009-06-05 20:12:451569 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441570
[email protected]5695b8c2009-09-30 21:36:431571 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441572
[email protected]1c773ea12009-04-28 19:58:421573 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441574 request.method = "GET";
1575 request.url = GURL("https://www.google.com/");
1576 request.load_flags = 0;
1577
1578 // Since we have proxy, should try to establish tunnel.
1579 MockWrite data_writes[] = {
1580 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451581 "Host: www.google.com\r\n"
1582 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441583 };
1584
1585 // The proxy responds to the connect with a 407.
1586 MockRead data_reads[] = {
1587 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1588 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1589 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421590 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441591 };
1592
[email protected]31a2bfe2010-02-09 08:03:391593 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1594 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591595 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441596
1597 TestCompletionCallback callback;
1598
[email protected]5a1d7ca2010-04-28 20:12:271599 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421600 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441601
1602 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421603 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441604
[email protected]1c773ea12009-04-28 19:58:421605 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441606 EXPECT_FALSE(response == NULL);
1607
1608 EXPECT_TRUE(response->headers->IsKeepAlive());
1609 EXPECT_EQ(407, response->headers->response_code());
1610 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421611 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441612
1613 std::string response_data;
1614 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421615 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181616
1617 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1618 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441619}
1620
[email protected]8fdbcd22010-05-05 02:54:521621// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1622// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1623TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1624 // We are using a DIRECT connection (i.e. no proxy) for this session.
1625 SessionDependencies session_deps;
1626 scoped_ptr<HttpTransaction> trans(
1627 new HttpNetworkTransaction(CreateSession(&session_deps)));
1628
1629 HttpRequestInfo request;
1630 request.method = "GET";
1631 request.url = GURL("http://www.google.com/");
1632 request.load_flags = 0;
1633
1634 MockWrite data_writes1[] = {
1635 MockWrite("GET / HTTP/1.1\r\n"
1636 "Host: www.google.com\r\n"
1637 "Connection: keep-alive\r\n\r\n"),
1638 };
1639
1640 MockRead data_reads1[] = {
1641 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1642 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1643 // Large content-length -- won't matter, as connection will be reset.
1644 MockRead("Content-Length: 10000\r\n\r\n"),
1645 MockRead(false, ERR_FAILED),
1646 };
1647
1648 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1649 data_writes1, arraysize(data_writes1));
1650 session_deps.socket_factory.AddSocketDataProvider(&data1);
1651
1652 TestCompletionCallback callback;
1653
1654 int rv = trans->Start(&request, &callback, BoundNetLog());
1655 EXPECT_EQ(ERR_IO_PENDING, rv);
1656
1657 rv = callback.WaitForResult();
1658 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1659}
1660
[email protected]ff007e162009-05-23 09:13:151661void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081662 const MockRead& status, int expected_status) {
1663 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591664 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081665
[email protected]228ff742009-06-05 01:19:591666 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081667
[email protected]5695b8c2009-09-30 21:36:431668 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081669
[email protected]1c773ea12009-04-28 19:58:421670 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081671 request.method = "GET";
1672 request.url = GURL("https://www.google.com/");
1673 request.load_flags = 0;
1674
1675 // Since we have proxy, should try to establish tunnel.
1676 MockWrite data_writes[] = {
1677 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451678 "Host: www.google.com\r\n"
1679 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081680 };
1681
1682 MockRead data_reads[] = {
1683 status,
1684 MockRead("Content-Length: 10\r\n\r\n"),
1685 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421686 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081687 };
1688
[email protected]31a2bfe2010-02-09 08:03:391689 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1690 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591691 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081692
1693 TestCompletionCallback callback;
1694
[email protected]5a1d7ca2010-04-28 20:12:271695 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421696 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081697
1698 rv = callback.WaitForResult();
1699 EXPECT_EQ(expected_status, rv);
1700}
1701
[email protected]ff007e162009-05-23 09:13:151702void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081703 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421704 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081705}
1706
1707TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1708 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1709}
1710
1711TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1712 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1713}
1714
1715TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1716 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1717}
1718
1719TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1720 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1721}
1722
1723TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1724 ConnectStatusHelper(
1725 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1726}
1727
1728TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1729 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1730}
1731
1732TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1733 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1734}
1735
1736TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1737 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1738}
1739
1740TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1741 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1742}
1743
1744TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1745 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1746}
1747
1748TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1749 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1750}
1751
1752TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1753 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1754}
1755
1756TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1757 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1758}
1759
1760TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1761 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1762}
1763
1764TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1765 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1766}
1767
1768TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1769 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1770}
1771
1772TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1773 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1774}
1775
1776TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1777 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1778}
1779
1780TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1781 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1782}
1783
1784TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1785 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1786}
1787
1788TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1789 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1790}
1791
1792TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1793 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1794}
1795
1796TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1797 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1798}
1799
1800TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1801 ConnectStatusHelperWithExpectedStatus(
1802 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541803 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081804}
1805
1806TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1807 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1808}
1809
1810TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1811 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1812}
1813
1814TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1815 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1816}
1817
1818TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1819 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1820}
1821
1822TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1823 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1824}
1825
1826TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1827 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1828}
1829
1830TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1831 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1832}
1833
1834TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1835 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1836}
1837
1838TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1839 ConnectStatusHelper(
1840 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1841}
1842
1843TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1844 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1845}
1846
1847TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1848 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1849}
1850
1851TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1852 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1853}
1854
1855TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1856 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1857}
1858
1859TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1860 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1861}
1862
1863TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1864 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1865}
1866
1867TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1868 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1869}
1870
[email protected]038e9a32008-10-08 22:40:161871// Test the flow when both the proxy server AND origin server require
1872// authentication. Again, this uses basic auth for both since that is
1873// the simplest to mock.
1874TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591875 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011876
[email protected]038e9a32008-10-08 22:40:161877 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421878 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431879 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161880
[email protected]1c773ea12009-04-28 19:58:421881 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161882 request.method = "GET";
1883 request.url = GURL("http://www.google.com/");
1884 request.load_flags = 0;
1885
[email protected]f9ee6b52008-11-08 06:46:231886 MockWrite data_writes1[] = {
1887 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1888 "Host: www.google.com\r\n"
1889 "Proxy-Connection: keep-alive\r\n\r\n"),
1890 };
1891
[email protected]038e9a32008-10-08 22:40:161892 MockRead data_reads1[] = {
1893 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1894 // Give a couple authenticate options (only the middle one is actually
1895 // supported).
[email protected]22927ad2009-09-21 19:56:191896 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161897 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1898 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1900 // Large content-length -- won't matter, as connection will be reset.
1901 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421902 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161903 };
1904
1905 // After calling trans->RestartWithAuth() the first time, this is the
1906 // request we should be issuing -- the final header line contains the
1907 // proxy's credentials.
1908 MockWrite data_writes2[] = {
1909 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1910 "Host: www.google.com\r\n"
1911 "Proxy-Connection: keep-alive\r\n"
1912 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1913 };
1914
1915 // Now the proxy server lets the request pass through to origin server.
1916 // The origin server responds with a 401.
1917 MockRead data_reads2[] = {
1918 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1919 // Note: We are using the same realm-name as the proxy server. This is
1920 // completely valid, as realms are unique across hosts.
1921 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1922 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1923 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421924 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161925 };
1926
1927 // After calling trans->RestartWithAuth() the second time, we should send
1928 // the credentials for both the proxy and origin server.
1929 MockWrite data_writes3[] = {
1930 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1931 "Host: www.google.com\r\n"
1932 "Proxy-Connection: keep-alive\r\n"
1933 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1934 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1935 };
1936
1937 // Lastly we get the desired content.
1938 MockRead data_reads3[] = {
1939 MockRead("HTTP/1.0 200 OK\r\n"),
1940 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1941 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421942 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161943 };
1944
[email protected]31a2bfe2010-02-09 08:03:391945 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1946 data_writes1, arraysize(data_writes1));
1947 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1948 data_writes2, arraysize(data_writes2));
1949 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1950 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591951 session_deps.socket_factory.AddSocketDataProvider(&data1);
1952 session_deps.socket_factory.AddSocketDataProvider(&data2);
1953 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161954
1955 TestCompletionCallback callback1;
1956
[email protected]5a1d7ca2010-04-28 20:12:271957 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421958 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161959
1960 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421961 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161962
[email protected]1c773ea12009-04-28 19:58:421963 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161964 EXPECT_FALSE(response == NULL);
1965
1966 // The password prompt info should have been set in response->auth_challenge.
1967 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1968
[email protected]71e4573a2009-05-21 22:03:001969 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161970 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1971 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1972
1973 TestCompletionCallback callback2;
1974
[email protected]13c8a092010-07-29 06:15:441975 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161977
1978 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421979 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161980
1981 response = trans->GetResponseInfo();
1982 EXPECT_FALSE(response == NULL);
1983 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1984
[email protected]71e4573a2009-05-21 22:03:001985 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161986 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1987 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1988
1989 TestCompletionCallback callback3;
1990
[email protected]13c8a092010-07-29 06:15:441991 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:421992 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161993
1994 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421995 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161996
1997 response = trans->GetResponseInfo();
1998 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1999 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162000}
[email protected]4ddaf2502008-10-23 18:26:192001
[email protected]ea9dc9a2009-09-05 00:43:322002// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2003// can't hook into its internals to cause it to generate predictable NTLM
2004// authorization headers.
2005#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292006// The NTLM authentication unit tests were generated by capturing the HTTP
2007// requests and responses using Fiddler 2 and inspecting the generated random
2008// bytes in the debugger.
2009
2010// Enter the correct password and authenticate successfully.
2011TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422012 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112013 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592014 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402015 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432016 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:242017
[email protected]1c773ea12009-04-28 19:58:422018 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242019 request.method = "GET";
2020 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2021 request.load_flags = 0;
2022
2023 MockWrite data_writes1[] = {
2024 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2025 "Host: 172.22.68.17\r\n"
2026 "Connection: keep-alive\r\n\r\n"),
2027 };
2028
2029 MockRead data_reads1[] = {
2030 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042031 // Negotiate and NTLM are often requested together. However, we only want
2032 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2033 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242034 MockRead("WWW-Authenticate: NTLM\r\n"),
2035 MockRead("Connection: close\r\n"),
2036 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362037 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242038 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422039 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242040 };
2041
2042 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222043 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242044 // request we should be issuing -- the final header line contains a Type
2045 // 1 message.
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"
2049 "Authorization: NTLM "
2050 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2051
2052 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2053 // (the credentials for the origin server). The second request continues
2054 // on the same connection.
2055 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2056 "Host: 172.22.68.17\r\n"
2057 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292058 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2059 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2060 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2061 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2062 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242063 };
2064
2065 MockRead data_reads2[] = {
2066 // The origin server responds with a Type 2 message.
2067 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2068 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292069 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242070 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2071 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2072 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2073 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2074 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2075 "BtAAAAAAA=\r\n"),
2076 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362077 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242078 MockRead("You are not authorized to view this page\r\n"),
2079
2080 // Lastly we get the desired content.
2081 MockRead("HTTP/1.1 200 OK\r\n"),
2082 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2083 MockRead("Content-Length: 13\r\n\r\n"),
2084 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422085 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242086 };
2087
[email protected]31a2bfe2010-02-09 08:03:392088 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2089 data_writes1, arraysize(data_writes1));
2090 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2091 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592092 session_deps.socket_factory.AddSocketDataProvider(&data1);
2093 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242094
2095 TestCompletionCallback callback1;
2096
[email protected]5a1d7ca2010-04-28 20:12:272097 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422098 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242099
2100 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422101 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242102
[email protected]0757e7702009-03-27 04:00:222103 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2104 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442105 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422106 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222107 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422108 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222109 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2110
[email protected]1c773ea12009-04-28 19:58:422111 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042112 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242113
[email protected]aef04272010-06-28 18:03:042114 // The password prompt info should have been set in
2115 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242116 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2117
[email protected]71e4573a2009-05-21 22:03:002118 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242119 EXPECT_EQ(L"", response->auth_challenge->realm);
2120 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2121
[email protected]0757e7702009-03-27 04:00:222122 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242123
[email protected]13c8a092010-07-29 06:15:442124 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422125 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242126
[email protected]0757e7702009-03-27 04:00:222127 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422128 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242129
2130 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042131 ASSERT_FALSE(response == NULL);
2132
[email protected]3f918782009-02-28 01:29:242133 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2134 EXPECT_EQ(13, response->headers->GetContentLength());
2135}
2136
[email protected]385a4672009-03-11 22:21:292137// Enter a wrong password, and then the correct one.
2138TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422139 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112140 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592141 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402142 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432143 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:292144
[email protected]1c773ea12009-04-28 19:58:422145 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292146 request.method = "GET";
2147 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2148 request.load_flags = 0;
2149
2150 MockWrite data_writes1[] = {
2151 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2152 "Host: 172.22.68.17\r\n"
2153 "Connection: keep-alive\r\n\r\n"),
2154 };
2155
2156 MockRead data_reads1[] = {
2157 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042158 // Negotiate and NTLM are often requested together. However, we only want
2159 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2160 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292161 MockRead("WWW-Authenticate: NTLM\r\n"),
2162 MockRead("Connection: close\r\n"),
2163 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362164 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292165 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422166 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292167 };
2168
2169 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222170 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292171 // request we should be issuing -- the final header line contains a Type
2172 // 1 message.
2173 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2174 "Host: 172.22.68.17\r\n"
2175 "Connection: keep-alive\r\n"
2176 "Authorization: NTLM "
2177 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2178
2179 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2180 // (the credentials for the origin server). The second request continues
2181 // on the same connection.
2182 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2183 "Host: 172.22.68.17\r\n"
2184 "Connection: keep-alive\r\n"
2185 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2186 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2187 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2188 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2189 "4Ww7b7E=\r\n\r\n"),
2190 };
2191
2192 MockRead data_reads2[] = {
2193 // The origin server responds with a Type 2 message.
2194 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2195 MockRead("WWW-Authenticate: NTLM "
2196 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2197 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2198 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2199 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2200 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2201 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2202 "BtAAAAAAA=\r\n"),
2203 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362204 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292205 MockRead("You are not authorized to view this page\r\n"),
2206
2207 // Wrong password.
2208 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292209 MockRead("WWW-Authenticate: NTLM\r\n"),
2210 MockRead("Connection: close\r\n"),
2211 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362212 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292213 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422214 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292215 };
2216
2217 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222218 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292219 // request we should be issuing -- the final header line contains a Type
2220 // 1 message.
2221 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2222 "Host: 172.22.68.17\r\n"
2223 "Connection: keep-alive\r\n"
2224 "Authorization: NTLM "
2225 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2226
2227 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2228 // (the credentials for the origin server). The second request continues
2229 // on the same connection.
2230 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2231 "Host: 172.22.68.17\r\n"
2232 "Connection: keep-alive\r\n"
2233 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2234 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2235 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2236 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2237 "+4MUm7c=\r\n\r\n"),
2238 };
2239
2240 MockRead data_reads3[] = {
2241 // The origin server responds with a Type 2 message.
2242 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2243 MockRead("WWW-Authenticate: NTLM "
2244 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2245 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2246 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2247 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2248 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2249 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2250 "BtAAAAAAA=\r\n"),
2251 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362252 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292253 MockRead("You are not authorized to view this page\r\n"),
2254
2255 // Lastly we get the desired content.
2256 MockRead("HTTP/1.1 200 OK\r\n"),
2257 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2258 MockRead("Content-Length: 13\r\n\r\n"),
2259 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422260 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292261 };
2262
[email protected]31a2bfe2010-02-09 08:03:392263 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2264 data_writes1, arraysize(data_writes1));
2265 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2266 data_writes2, arraysize(data_writes2));
2267 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2268 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592269 session_deps.socket_factory.AddSocketDataProvider(&data1);
2270 session_deps.socket_factory.AddSocketDataProvider(&data2);
2271 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292272
2273 TestCompletionCallback callback1;
2274
[email protected]5a1d7ca2010-04-28 20:12:272275 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422276 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292277
2278 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422279 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292280
[email protected]0757e7702009-03-27 04:00:222281 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292282 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442283 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422284 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292285 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422286 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222287 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292288
[email protected]1c773ea12009-04-28 19:58:422289 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292290 EXPECT_FALSE(response == NULL);
2291
2292 // The password prompt info should have been set in response->auth_challenge.
2293 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2294
[email protected]71e4573a2009-05-21 22:03:002295 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292296 EXPECT_EQ(L"", response->auth_challenge->realm);
2297 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2298
2299 TestCompletionCallback callback3;
2300
[email protected]0757e7702009-03-27 04:00:222301 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442302 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422303 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292304
2305 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422306 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292307
[email protected]0757e7702009-03-27 04:00:222308 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2309 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442310 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422311 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222312 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422313 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222314 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2315
2316 response = trans->GetResponseInfo();
2317 EXPECT_FALSE(response == NULL);
2318
2319 // The password prompt info should have been set in response->auth_challenge.
2320 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2321
[email protected]71e4573a2009-05-21 22:03:002322 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222323 EXPECT_EQ(L"", response->auth_challenge->realm);
2324 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2325
2326 TestCompletionCallback callback5;
2327
2328 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442329 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422330 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222331
2332 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422333 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222334
[email protected]385a4672009-03-11 22:21:292335 response = trans->GetResponseInfo();
2336 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2337 EXPECT_EQ(13, response->headers->GetContentLength());
2338}
[email protected]ea9dc9a2009-09-05 00:43:322339#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292340
[email protected]4ddaf2502008-10-23 18:26:192341// Test reading a server response which has only headers, and no body.
2342// After some maximum number of bytes is consumed, the transaction should
2343// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2344TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592345 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402346 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432347 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192348
[email protected]1c773ea12009-04-28 19:58:422349 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192350 request.method = "GET";
2351 request.url = GURL("http://www.google.com/");
2352 request.load_flags = 0;
2353
[email protected]b75b7b2f2009-10-06 00:54:532354 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432355 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532356 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192357
2358 MockRead data_reads[] = {
2359 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432360 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192361 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422362 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192363 };
[email protected]31a2bfe2010-02-09 08:03:392364 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592365 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192366
2367 TestCompletionCallback callback;
2368
[email protected]5a1d7ca2010-04-28 20:12:272369 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422370 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192371
2372 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422373 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192374
[email protected]1c773ea12009-04-28 19:58:422375 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192376 EXPECT_TRUE(response == NULL);
2377}
[email protected]f4e426b2008-11-05 00:24:492378
2379// Make sure that we don't try to reuse a TCPClientSocket when failing to
2380// establish tunnel.
2381// http://code.google.com/p/chromium/issues/detail?id=3772
2382TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2383 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592384 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012385
[email protected]228ff742009-06-05 01:19:592386 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492387
[email protected]5695b8c2009-09-30 21:36:432388 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492389
[email protected]1c773ea12009-04-28 19:58:422390 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492391 request.method = "GET";
2392 request.url = GURL("https://www.google.com/");
2393 request.load_flags = 0;
2394
2395 // Since we have proxy, should try to establish tunnel.
2396 MockWrite data_writes1[] = {
2397 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452398 "Host: www.google.com\r\n"
2399 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492400 };
2401
[email protected]77848d12008-11-14 00:00:222402 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492403 // connection. Usually a proxy would return 501 (not implemented),
2404 // or 200 (tunnel established).
2405 MockRead data_reads1[] = {
2406 MockRead("HTTP/1.1 404 Not Found\r\n"),
2407 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422408 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492409 };
2410
[email protected]31a2bfe2010-02-09 08:03:392411 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2412 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592413 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492414
2415 TestCompletionCallback callback1;
2416
[email protected]5a1d7ca2010-04-28 20:12:272417 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422418 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492419
2420 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422421 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492422
[email protected]1c773ea12009-04-28 19:58:422423 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082424 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492425
[email protected]b4404c02009-04-10 16:38:522426 // Empty the current queue. This is necessary because idle sockets are
2427 // added to the connection pool asynchronously with a PostTask.
2428 MessageLoop::current()->RunAllPending();
2429
[email protected]f4e426b2008-11-05 00:24:492430 // We now check to make sure the TCPClientSocket was not added back to
2431 // the pool.
[email protected]a937a06d2009-08-19 21:19:242432 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492433 trans.reset();
[email protected]b4404c02009-04-10 16:38:522434 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492435 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242436 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492437}
[email protected]372d34a2008-11-05 21:30:512438
[email protected]1b157c02009-04-21 01:55:402439// Make sure that we recycle a socket after reading all of the response body.
2440TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592441 SessionDependencies session_deps;
2442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402443
[email protected]5695b8c2009-09-30 21:36:432444 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402445
[email protected]1c773ea12009-04-28 19:58:422446 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402447 request.method = "GET";
2448 request.url = GURL("http://www.google.com/");
2449 request.load_flags = 0;
2450
2451 MockRead data_reads[] = {
2452 // A part of the response body is received with the response headers.
2453 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2454 // The rest of the response body is received in two parts.
2455 MockRead("lo"),
2456 MockRead(" world"),
2457 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422458 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402459 };
2460
[email protected]31a2bfe2010-02-09 08:03:392461 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592462 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402463
2464 TestCompletionCallback callback;
2465
[email protected]5a1d7ca2010-04-28 20:12:272466 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422467 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402468
2469 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422470 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402471
[email protected]1c773ea12009-04-28 19:58:422472 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402473 EXPECT_TRUE(response != NULL);
2474
2475 EXPECT_TRUE(response->headers != NULL);
2476 std::string status_line = response->headers->GetStatusLine();
2477 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2478
[email protected]a937a06d2009-08-19 21:19:242479 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402480
2481 std::string response_data;
2482 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422483 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402484 EXPECT_EQ("hello world", response_data);
2485
2486 // Empty the current queue. This is necessary because idle sockets are
2487 // added to the connection pool asynchronously with a PostTask.
2488 MessageLoop::current()->RunAllPending();
2489
2490 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242491 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402492}
2493
[email protected]b4404c02009-04-10 16:38:522494// Make sure that we recycle a socket after a zero-length response.
2495// http://crbug.com/9880
2496TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592497 SessionDependencies session_deps;
2498 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522499
[email protected]5695b8c2009-09-30 21:36:432500 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522501
[email protected]1c773ea12009-04-28 19:58:422502 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522503 request.method = "GET";
2504 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2505 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2506 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2507 "rt=prt.2642,ol.2649,xjs.2951");
2508 request.load_flags = 0;
2509
2510 MockRead data_reads[] = {
2511 MockRead("HTTP/1.1 204 No Content\r\n"
2512 "Content-Length: 0\r\n"
2513 "Content-Type: text/html\r\n\r\n"),
2514 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422515 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522516 };
2517
[email protected]31a2bfe2010-02-09 08:03:392518 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592519 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522520
2521 TestCompletionCallback callback;
2522
[email protected]5a1d7ca2010-04-28 20:12:272523 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422524 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522525
2526 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422527 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522528
[email protected]1c773ea12009-04-28 19:58:422529 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522530 EXPECT_TRUE(response != NULL);
2531
2532 EXPECT_TRUE(response->headers != NULL);
2533 std::string status_line = response->headers->GetStatusLine();
2534 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2535
[email protected]a937a06d2009-08-19 21:19:242536 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522537
2538 std::string response_data;
2539 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422540 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522541 EXPECT_EQ("", response_data);
2542
2543 // Empty the current queue. This is necessary because idle sockets are
2544 // added to the connection pool asynchronously with a PostTask.
2545 MessageLoop::current()->RunAllPending();
2546
2547 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242548 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522549}
2550
[email protected]372d34a2008-11-05 21:30:512551TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422552 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512553 // Transaction 1: a GET request that succeeds. The socket is recycled
2554 // after use.
2555 request[0].method = "GET";
2556 request[0].url = GURL("http://www.google.com/");
2557 request[0].load_flags = 0;
2558 // Transaction 2: a POST request. Reuses the socket kept alive from
2559 // transaction 1. The first attempts fails when writing the POST data.
2560 // This causes the transaction to retry with a new socket. The second
2561 // attempt succeeds.
2562 request[1].method = "POST";
2563 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422564 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512565 request[1].upload_data->AppendBytes("foo", 3);
2566 request[1].load_flags = 0;
2567
[email protected]228ff742009-06-05 01:19:592568 SessionDependencies session_deps;
2569 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512570
2571 // The first socket is used for transaction 1 and the first attempt of
2572 // transaction 2.
2573
2574 // The response of transaction 1.
2575 MockRead data_reads1[] = {
2576 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2577 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422578 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512579 };
2580 // The mock write results of transaction 1 and the first attempt of
2581 // transaction 2.
2582 MockWrite data_writes1[] = {
2583 MockWrite(false, 64), // GET
2584 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422585 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512586 };
[email protected]31a2bfe2010-02-09 08:03:392587 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2588 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512589
2590 // The second socket is used for the second attempt of transaction 2.
2591
2592 // The response of transaction 2.
2593 MockRead data_reads2[] = {
2594 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2595 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422596 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512597 };
2598 // The mock write results of the second attempt of transaction 2.
2599 MockWrite data_writes2[] = {
2600 MockWrite(false, 93), // POST
2601 MockWrite(false, 3), // POST data
2602 };
[email protected]31a2bfe2010-02-09 08:03:392603 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2604 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512605
[email protected]5ecc992a42009-11-11 01:41:592606 session_deps.socket_factory.AddSocketDataProvider(&data1);
2607 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512608
2609 const char* kExpectedResponseData[] = {
2610 "hello world", "welcome"
2611 };
2612
2613 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422614 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432615 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512616
2617 TestCompletionCallback callback;
2618
[email protected]5a1d7ca2010-04-28 20:12:272619 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422620 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512621
2622 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422623 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512624
[email protected]1c773ea12009-04-28 19:58:422625 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512626 EXPECT_TRUE(response != NULL);
2627
2628 EXPECT_TRUE(response->headers != NULL);
2629 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2630
2631 std::string response_data;
2632 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422633 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512634 EXPECT_EQ(kExpectedResponseData[i], response_data);
2635 }
2636}
[email protected]f9ee6b52008-11-08 06:46:232637
2638// Test the request-challenge-retry sequence for basic auth when there is
2639// an identity in the URL. The request should be sent as normal, but when
2640// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322641TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592642 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402643 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432644 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232645
[email protected]1c773ea12009-04-28 19:58:422646 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232647 request.method = "GET";
2648 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292649 request.url = GURL("http://foo:b@[email protected]/");
2650
2651 // The password contains an escaped character -- for this test to pass it
2652 // will need to be unescaped by HttpNetworkTransaction.
2653 EXPECT_EQ("b%40r", request.url.password());
2654
[email protected]ea9dc9a2009-09-05 00:43:322655 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232656
2657 MockWrite data_writes1[] = {
2658 MockWrite("GET / HTTP/1.1\r\n"
2659 "Host: www.google.com\r\n"
2660 "Connection: keep-alive\r\n\r\n"),
2661 };
2662
2663 MockRead data_reads1[] = {
2664 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2665 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2666 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422667 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232668 };
2669
2670 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322671 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232672 MockWrite data_writes2[] = {
2673 MockWrite("GET / HTTP/1.1\r\n"
2674 "Host: www.google.com\r\n"
2675 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292676 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232677 };
2678
2679 MockRead data_reads2[] = {
2680 MockRead("HTTP/1.0 200 OK\r\n"),
2681 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422682 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232683 };
2684
[email protected]31a2bfe2010-02-09 08:03:392685 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2686 data_writes1, arraysize(data_writes1));
2687 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2688 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592689 session_deps.socket_factory.AddSocketDataProvider(&data1);
2690 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232691
2692 TestCompletionCallback callback1;
2693
[email protected]5a1d7ca2010-04-28 20:12:272694 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422695 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232696
2697 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422698 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232699
[email protected]0757e7702009-03-27 04:00:222700 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2701 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442702 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422703 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222704 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422705 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222706 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2707
[email protected]1c773ea12009-04-28 19:58:422708 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232709 EXPECT_FALSE(response == NULL);
2710
2711 // There is no challenge info, since the identity in URL worked.
2712 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2713
2714 EXPECT_EQ(100, response->headers->GetContentLength());
2715
2716 // Empty the current queue.
2717 MessageLoop::current()->RunAllPending();
2718}
2719
[email protected]ea9dc9a2009-09-05 00:43:322720// Test the request-challenge-retry sequence for basic auth when there is
2721// an incorrect identity in the URL. The identity from the URL should be used
2722// only once.
2723TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2724 SessionDependencies session_deps;
2725 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432726 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322727
2728 HttpRequestInfo request;
2729 request.method = "GET";
2730 // Note: the URL has a username:password in it. The password "baz" is
2731 // wrong (should be "bar").
2732 request.url = GURL("http://foo:[email protected]/");
2733
2734 request.load_flags = LOAD_NORMAL;
2735
2736 MockWrite data_writes1[] = {
2737 MockWrite("GET / HTTP/1.1\r\n"
2738 "Host: www.google.com\r\n"
2739 "Connection: keep-alive\r\n\r\n"),
2740 };
2741
2742 MockRead data_reads1[] = {
2743 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2744 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2745 MockRead("Content-Length: 10\r\n\r\n"),
2746 MockRead(false, ERR_FAILED),
2747 };
2748
2749 // After the challenge above, the transaction will be restarted using the
2750 // identity from the url (foo, baz) to answer the challenge.
2751 MockWrite data_writes2[] = {
2752 MockWrite("GET / HTTP/1.1\r\n"
2753 "Host: www.google.com\r\n"
2754 "Connection: keep-alive\r\n"
2755 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2756 };
2757
2758 MockRead data_reads2[] = {
2759 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2760 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2761 MockRead("Content-Length: 10\r\n\r\n"),
2762 MockRead(false, ERR_FAILED),
2763 };
2764
2765 // After the challenge above, the transaction will be restarted using the
2766 // identity supplied by the user (foo, bar) to answer the challenge.
2767 MockWrite data_writes3[] = {
2768 MockWrite("GET / HTTP/1.1\r\n"
2769 "Host: www.google.com\r\n"
2770 "Connection: keep-alive\r\n"
2771 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2772 };
2773
2774 MockRead data_reads3[] = {
2775 MockRead("HTTP/1.0 200 OK\r\n"),
2776 MockRead("Content-Length: 100\r\n\r\n"),
2777 MockRead(false, OK),
2778 };
2779
[email protected]31a2bfe2010-02-09 08:03:392780 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2781 data_writes1, arraysize(data_writes1));
2782 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2783 data_writes2, arraysize(data_writes2));
2784 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2785 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592786 session_deps.socket_factory.AddSocketDataProvider(&data1);
2787 session_deps.socket_factory.AddSocketDataProvider(&data2);
2788 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322789
2790 TestCompletionCallback callback1;
2791
[email protected]5a1d7ca2010-04-28 20:12:272792 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322793 EXPECT_EQ(ERR_IO_PENDING, rv);
2794
2795 rv = callback1.WaitForResult();
2796 EXPECT_EQ(OK, rv);
2797
2798 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2799 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442800 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:322801 EXPECT_EQ(ERR_IO_PENDING, rv);
2802 rv = callback2.WaitForResult();
2803 EXPECT_EQ(OK, rv);
2804 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2805
2806 const HttpResponseInfo* response = trans->GetResponseInfo();
2807 EXPECT_FALSE(response == NULL);
2808 // The password prompt info should have been set in response->auth_challenge.
2809 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2810
2811 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2812 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2813 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2814
2815 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:442816 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:322817 EXPECT_EQ(ERR_IO_PENDING, rv);
2818 rv = callback3.WaitForResult();
2819 EXPECT_EQ(OK, rv);
2820 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2821
2822 response = trans->GetResponseInfo();
2823 EXPECT_FALSE(response == NULL);
2824
2825 // There is no challenge info, since the identity worked.
2826 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2827
2828 EXPECT_EQ(100, response->headers->GetContentLength());
2829
2830 // Empty the current queue.
2831 MessageLoop::current()->RunAllPending();
2832}
2833
[email protected]f9ee6b52008-11-08 06:46:232834// Test that previously tried username/passwords for a realm get re-used.
2835TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592836 SessionDependencies session_deps;
2837 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232838
2839 // Transaction 1: authenticate (foo, bar) on MyRealm1
2840 {
[email protected]5695b8c2009-09-30 21:36:432841 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232842
[email protected]1c773ea12009-04-28 19:58:422843 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232844 request.method = "GET";
2845 request.url = GURL("http://www.google.com/x/y/z");
2846 request.load_flags = 0;
2847
2848 MockWrite data_writes1[] = {
2849 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2850 "Host: www.google.com\r\n"
2851 "Connection: keep-alive\r\n\r\n"),
2852 };
2853
2854 MockRead data_reads1[] = {
2855 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2856 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2857 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422858 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232859 };
2860
2861 // Resend with authorization (username=foo, password=bar)
2862 MockWrite data_writes2[] = {
2863 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2864 "Host: www.google.com\r\n"
2865 "Connection: keep-alive\r\n"
2866 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2867 };
2868
2869 // Sever accepts the authorization.
2870 MockRead data_reads2[] = {
2871 MockRead("HTTP/1.0 200 OK\r\n"),
2872 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422873 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232874 };
2875
[email protected]31a2bfe2010-02-09 08:03:392876 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2877 data_writes1, arraysize(data_writes1));
2878 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2879 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592880 session_deps.socket_factory.AddSocketDataProvider(&data1);
2881 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232882
2883 TestCompletionCallback callback1;
2884
[email protected]5a1d7ca2010-04-28 20:12:272885 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422886 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232887
2888 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422889 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232890
[email protected]1c773ea12009-04-28 19:58:422891 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232892 EXPECT_FALSE(response == NULL);
2893
2894 // The password prompt info should have been set in
2895 // response->auth_challenge.
2896 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2897
[email protected]71e4573a2009-05-21 22:03:002898 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232899 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2900 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2901
2902 TestCompletionCallback callback2;
2903
[email protected]13c8a092010-07-29 06:15:442904 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422905 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232906
2907 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422908 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232909
2910 response = trans->GetResponseInfo();
2911 EXPECT_FALSE(response == NULL);
2912 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2913 EXPECT_EQ(100, response->headers->GetContentLength());
2914 }
2915
2916 // ------------------------------------------------------------------------
2917
2918 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2919 {
[email protected]5695b8c2009-09-30 21:36:432920 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232921
[email protected]1c773ea12009-04-28 19:58:422922 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232923 request.method = "GET";
2924 // Note that Transaction 1 was at /x/y/z, so this is in the same
2925 // protection space as MyRealm1.
2926 request.url = GURL("http://www.google.com/x/y/a/b");
2927 request.load_flags = 0;
2928
2929 MockWrite data_writes1[] = {
2930 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2931 "Host: www.google.com\r\n"
2932 "Connection: keep-alive\r\n"
2933 // Send preemptive authorization for MyRealm1
2934 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2935 };
2936
2937 // The server didn't like the preemptive authorization, and
2938 // challenges us for a different realm (MyRealm2).
2939 MockRead data_reads1[] = {
2940 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2941 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2942 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422943 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232944 };
2945
2946 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2947 MockWrite data_writes2[] = {
2948 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2949 "Host: www.google.com\r\n"
2950 "Connection: keep-alive\r\n"
2951 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2952 };
2953
2954 // Sever accepts the authorization.
2955 MockRead data_reads2[] = {
2956 MockRead("HTTP/1.0 200 OK\r\n"),
2957 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422958 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232959 };
2960
[email protected]31a2bfe2010-02-09 08:03:392961 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2962 data_writes1, arraysize(data_writes1));
2963 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2964 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592965 session_deps.socket_factory.AddSocketDataProvider(&data1);
2966 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232967
2968 TestCompletionCallback callback1;
2969
[email protected]5a1d7ca2010-04-28 20:12:272970 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422971 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232972
2973 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422974 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232975
[email protected]1c773ea12009-04-28 19:58:422976 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232977 EXPECT_FALSE(response == NULL);
2978
2979 // The password prompt info should have been set in
2980 // response->auth_challenge.
2981 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2982
[email protected]71e4573a2009-05-21 22:03:002983 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232984 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2985 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2986
2987 TestCompletionCallback callback2;
2988
[email protected]13c8a092010-07-29 06:15:442989 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:422990 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232991
2992 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422993 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232994
2995 response = trans->GetResponseInfo();
2996 EXPECT_FALSE(response == NULL);
2997 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2998 EXPECT_EQ(100, response->headers->GetContentLength());
2999 }
3000
3001 // ------------------------------------------------------------------------
3002
3003 // Transaction 3: Resend a request in MyRealm's protection space --
3004 // succeed with preemptive authorization.
3005 {
[email protected]5695b8c2009-09-30 21:36:433006 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233007
[email protected]1c773ea12009-04-28 19:58:423008 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233009 request.method = "GET";
3010 request.url = GURL("http://www.google.com/x/y/z2");
3011 request.load_flags = 0;
3012
3013 MockWrite data_writes1[] = {
3014 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3015 "Host: www.google.com\r\n"
3016 "Connection: keep-alive\r\n"
3017 // The authorization for MyRealm1 gets sent preemptively
3018 // (since the url is in the same protection space)
3019 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3020 };
3021
3022 // Sever accepts the preemptive authorization
3023 MockRead data_reads1[] = {
3024 MockRead("HTTP/1.0 200 OK\r\n"),
3025 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423026 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233027 };
3028
[email protected]31a2bfe2010-02-09 08:03:393029 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3030 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593031 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233032
3033 TestCompletionCallback callback1;
3034
[email protected]5a1d7ca2010-04-28 20:12:273035 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423036 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233037
3038 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423039 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233040
[email protected]1c773ea12009-04-28 19:58:423041 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233042 EXPECT_FALSE(response == NULL);
3043
3044 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3045 EXPECT_EQ(100, response->headers->GetContentLength());
3046 }
3047
3048 // ------------------------------------------------------------------------
3049
3050 // Transaction 4: request another URL in MyRealm (however the
3051 // url is not known to belong to the protection space, so no pre-auth).
3052 {
[email protected]5695b8c2009-09-30 21:36:433053 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233054
[email protected]1c773ea12009-04-28 19:58:423055 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233056 request.method = "GET";
3057 request.url = GURL("http://www.google.com/x/1");
3058 request.load_flags = 0;
3059
3060 MockWrite data_writes1[] = {
3061 MockWrite("GET /x/1 HTTP/1.1\r\n"
3062 "Host: www.google.com\r\n"
3063 "Connection: keep-alive\r\n\r\n"),
3064 };
3065
3066 MockRead data_reads1[] = {
3067 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3068 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3069 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423070 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233071 };
3072
3073 // Resend with authorization from MyRealm's cache.
3074 MockWrite data_writes2[] = {
3075 MockWrite("GET /x/1 HTTP/1.1\r\n"
3076 "Host: www.google.com\r\n"
3077 "Connection: keep-alive\r\n"
3078 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3079 };
3080
3081 // Sever accepts the authorization.
3082 MockRead data_reads2[] = {
3083 MockRead("HTTP/1.0 200 OK\r\n"),
3084 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423085 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233086 };
3087
[email protected]31a2bfe2010-02-09 08:03:393088 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3089 data_writes1, arraysize(data_writes1));
3090 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3091 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593092 session_deps.socket_factory.AddSocketDataProvider(&data1);
3093 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233094
3095 TestCompletionCallback callback1;
3096
[email protected]5a1d7ca2010-04-28 20:12:273097 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423098 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233099
3100 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423101 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233102
[email protected]0757e7702009-03-27 04:00:223103 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3104 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443105 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423106 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223107 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423108 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223109 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3110
[email protected]1c773ea12009-04-28 19:58:423111 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233112 EXPECT_FALSE(response == NULL);
3113 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3114 EXPECT_EQ(100, response->headers->GetContentLength());
3115 }
3116
3117 // ------------------------------------------------------------------------
3118
3119 // Transaction 5: request a URL in MyRealm, but the server rejects the
3120 // cached identity. Should invalidate and re-prompt.
3121 {
[email protected]5695b8c2009-09-30 21:36:433122 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233123
[email protected]1c773ea12009-04-28 19:58:423124 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233125 request.method = "GET";
3126 request.url = GURL("http://www.google.com/p/q/t");
3127 request.load_flags = 0;
3128
3129 MockWrite data_writes1[] = {
3130 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3131 "Host: www.google.com\r\n"
3132 "Connection: keep-alive\r\n\r\n"),
3133 };
3134
3135 MockRead data_reads1[] = {
3136 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3137 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3138 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423139 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233140 };
3141
3142 // Resend with authorization from cache for MyRealm.
3143 MockWrite data_writes2[] = {
3144 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3145 "Host: www.google.com\r\n"
3146 "Connection: keep-alive\r\n"
3147 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3148 };
3149
3150 // Sever rejects the authorization.
3151 MockRead data_reads2[] = {
3152 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3153 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3154 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423155 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233156 };
3157
3158 // At this point we should prompt for new credentials for MyRealm.
3159 // Restart with username=foo3, password=foo4.
3160 MockWrite data_writes3[] = {
3161 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3162 "Host: www.google.com\r\n"
3163 "Connection: keep-alive\r\n"
3164 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3165 };
3166
3167 // Sever accepts the authorization.
3168 MockRead data_reads3[] = {
3169 MockRead("HTTP/1.0 200 OK\r\n"),
3170 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423171 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233172 };
3173
[email protected]31a2bfe2010-02-09 08:03:393174 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3175 data_writes1, arraysize(data_writes1));
3176 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3177 data_writes2, arraysize(data_writes2));
3178 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3179 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593180 session_deps.socket_factory.AddSocketDataProvider(&data1);
3181 session_deps.socket_factory.AddSocketDataProvider(&data2);
3182 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233183
3184 TestCompletionCallback callback1;
3185
[email protected]5a1d7ca2010-04-28 20:12:273186 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423187 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233188
3189 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423190 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233191
[email protected]0757e7702009-03-27 04:00:223192 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3193 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443194 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423195 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223196 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423197 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223198 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3199
[email protected]1c773ea12009-04-28 19:58:423200 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233201 EXPECT_FALSE(response == NULL);
3202
3203 // The password prompt info should have been set in
3204 // response->auth_challenge.
3205 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3206
[email protected]71e4573a2009-05-21 22:03:003207 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233208 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3209 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3210
[email protected]0757e7702009-03-27 04:00:223211 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233212
[email protected]13c8a092010-07-29 06:15:443213 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423214 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233215
[email protected]0757e7702009-03-27 04:00:223216 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423217 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233218
3219 response = trans->GetResponseInfo();
3220 EXPECT_FALSE(response == NULL);
3221 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3222 EXPECT_EQ(100, response->headers->GetContentLength());
3223 }
3224}
[email protected]89ceba9a2009-03-21 03:46:063225
[email protected]3c32c5f2010-05-18 15:18:123226// Tests that nonce count increments when multiple auth attempts
3227// are started with the same nonce.
3228TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3229 SessionDependencies session_deps;
3230 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3231 HttpAuthHandlerDigest::SetFixedCnonce(true);
3232
3233 // Transaction 1: authenticate (foo, bar) on MyRealm1
3234 {
3235 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3236
3237 HttpRequestInfo request;
3238 request.method = "GET";
3239 request.url = GURL("http://www.google.com/x/y/z");
3240 request.load_flags = 0;
3241
3242 MockWrite data_writes1[] = {
3243 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3244 "Host: www.google.com\r\n"
3245 "Connection: keep-alive\r\n\r\n"),
3246 };
3247
3248 MockRead data_reads1[] = {
3249 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3250 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3251 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3252 MockRead(false, OK),
3253 };
3254
3255 // Resend with authorization (username=foo, password=bar)
3256 MockWrite data_writes2[] = {
3257 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3258 "Host: www.google.com\r\n"
3259 "Connection: keep-alive\r\n"
3260 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3261 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3262 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3263 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3264 };
3265
3266 // Sever accepts the authorization.
3267 MockRead data_reads2[] = {
3268 MockRead("HTTP/1.0 200 OK\r\n"),
3269 MockRead(false, OK),
3270 };
3271
3272 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3273 data_writes1, arraysize(data_writes1));
3274 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3275 data_writes2, arraysize(data_writes2));
3276 session_deps.socket_factory.AddSocketDataProvider(&data1);
3277 session_deps.socket_factory.AddSocketDataProvider(&data2);
3278
3279 TestCompletionCallback callback1;
3280
3281 int rv = trans->Start(&request, &callback1, BoundNetLog());
3282 EXPECT_EQ(ERR_IO_PENDING, rv);
3283
3284 rv = callback1.WaitForResult();
3285 EXPECT_EQ(OK, rv);
3286
3287 const HttpResponseInfo* response = trans->GetResponseInfo();
3288 ASSERT_FALSE(response == NULL);
3289
3290 // The password prompt info should have been set in
3291 // response->auth_challenge.
3292 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3293
3294 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3295 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3296 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3297
3298 TestCompletionCallback callback2;
3299
[email protected]13c8a092010-07-29 06:15:443300 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123301 EXPECT_EQ(ERR_IO_PENDING, rv);
3302
3303 rv = callback2.WaitForResult();
3304 EXPECT_EQ(OK, rv);
3305
3306 response = trans->GetResponseInfo();
3307 ASSERT_FALSE(response == NULL);
3308 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3309 }
3310
3311 // ------------------------------------------------------------------------
3312
3313 // Transaction 2: Request another resource in digestive's protection space.
3314 // This will preemptively add an Authorization header which should have an
3315 // "nc" value of 2 (as compared to 1 in the first use.
3316 {
3317 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3318
3319 HttpRequestInfo request;
3320 request.method = "GET";
3321 // Note that Transaction 1 was at /x/y/z, so this is in the same
3322 // protection space as digest.
3323 request.url = GURL("http://www.google.com/x/y/a/b");
3324 request.load_flags = 0;
3325
3326 MockWrite data_writes1[] = {
3327 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3328 "Host: www.google.com\r\n"
3329 "Connection: keep-alive\r\n"
3330 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3331 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3332 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3333 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3334 };
3335
3336 // Sever accepts the authorization.
3337 MockRead data_reads1[] = {
3338 MockRead("HTTP/1.0 200 OK\r\n"),
3339 MockRead("Content-Length: 100\r\n\r\n"),
3340 MockRead(false, OK),
3341 };
3342
3343 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3344 data_writes1, arraysize(data_writes1));
3345 session_deps.socket_factory.AddSocketDataProvider(&data1);
3346
3347 TestCompletionCallback callback1;
3348
3349 int rv = trans->Start(&request, &callback1, BoundNetLog());
3350 EXPECT_EQ(ERR_IO_PENDING, rv);
3351
3352 rv = callback1.WaitForResult();
3353 EXPECT_EQ(OK, rv);
3354
3355 const HttpResponseInfo* response = trans->GetResponseInfo();
3356 ASSERT_FALSE(response == NULL);
3357 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3358 }
3359}
3360
[email protected]89ceba9a2009-03-21 03:46:063361// Test the ResetStateForRestart() private method.
3362TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3363 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593364 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403365 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433366 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063367
3368 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063369 trans->read_buf_ = new IOBuffer(15);
3370 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573371 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063372
3373 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143374 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573375 response->auth_challenge = new AuthChallengeInfo();
3376 response->ssl_info.cert_status = -15;
3377 response->response_time = base::Time::Now();
3378 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063379
3380 { // Setup state for response_.vary_data
3381 HttpRequestInfo request;
3382 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3383 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573384 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433385 request.extra_headers.SetHeader("Foo", "1");
3386 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573387 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063388 }
3389
3390 // Cause the above state to be reset.
3391 trans->ResetStateForRestart();
3392
3393 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073394 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063395 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573396 EXPECT_EQ(0U, trans->request_headers_.size());
3397 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3398 EXPECT_TRUE(response->headers.get() == NULL);
3399 EXPECT_EQ(false, response->was_cached);
3400 EXPECT_EQ(0, response->ssl_info.cert_status);
3401 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063402}
3403
[email protected]bacff652009-03-31 17:50:333404// Test HTTPS connections to a site with a bad certificate
3405TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593406 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403407 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433408 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333409
3410 HttpRequestInfo request;
3411 request.method = "GET";
3412 request.url = GURL("https://www.google.com/");
3413 request.load_flags = 0;
3414
3415 MockWrite data_writes[] = {
3416 MockWrite("GET / HTTP/1.1\r\n"
3417 "Host: www.google.com\r\n"
3418 "Connection: keep-alive\r\n\r\n"),
3419 };
3420
3421 MockRead data_reads[] = {
3422 MockRead("HTTP/1.0 200 OK\r\n"),
3423 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3424 MockRead("Content-Length: 100\r\n\r\n"),
3425 MockRead(false, OK),
3426 };
3427
[email protected]5ecc992a42009-11-11 01:41:593428 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393429 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3430 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593431 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3432 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333433
[email protected]5ecc992a42009-11-11 01:41:593434 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3435 session_deps.socket_factory.AddSocketDataProvider(&data);
3436 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3437 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333438
3439 TestCompletionCallback callback;
3440
[email protected]5a1d7ca2010-04-28 20:12:273441 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333442 EXPECT_EQ(ERR_IO_PENDING, rv);
3443
3444 rv = callback.WaitForResult();
3445 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3446
3447 rv = trans->RestartIgnoringLastError(&callback);
3448 EXPECT_EQ(ERR_IO_PENDING, rv);
3449
3450 rv = callback.WaitForResult();
3451 EXPECT_EQ(OK, rv);
3452
3453 const HttpResponseInfo* response = trans->GetResponseInfo();
3454
3455 EXPECT_FALSE(response == NULL);
3456 EXPECT_EQ(100, response->headers->GetContentLength());
3457}
3458
3459// Test HTTPS connections to a site with a bad certificate, going through a
3460// proxy
3461TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593462 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333463
3464 HttpRequestInfo request;
3465 request.method = "GET";
3466 request.url = GURL("https://www.google.com/");
3467 request.load_flags = 0;
3468
3469 MockWrite proxy_writes[] = {
3470 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453471 "Host: www.google.com\r\n"
3472 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333473 };
3474
3475 MockRead proxy_reads[] = {
3476 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423477 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333478 };
3479
3480 MockWrite data_writes[] = {
3481 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453482 "Host: www.google.com\r\n"
3483 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333484 MockWrite("GET / HTTP/1.1\r\n"
3485 "Host: www.google.com\r\n"
3486 "Connection: keep-alive\r\n\r\n"),
3487 };
3488
3489 MockRead data_reads[] = {
3490 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
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 ssl_bad_certificate(
3498 proxy_reads, arraysize(proxy_reads),
3499 proxy_writes, arraysize(proxy_writes));
3500 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3501 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593502 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3503 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333504
[email protected]5ecc992a42009-11-11 01:41:593505 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3506 session_deps.socket_factory.AddSocketDataProvider(&data);
3507 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3508 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333509
3510 TestCompletionCallback callback;
3511
3512 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593513 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333514
[email protected]d207a5f2009-06-04 05:28:403515 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433516 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333517
[email protected]5a1d7ca2010-04-28 20:12:273518 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333519 EXPECT_EQ(ERR_IO_PENDING, rv);
3520
3521 rv = callback.WaitForResult();
3522 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3523
3524 rv = trans->RestartIgnoringLastError(&callback);
3525 EXPECT_EQ(ERR_IO_PENDING, rv);
3526
3527 rv = callback.WaitForResult();
3528 EXPECT_EQ(OK, rv);
3529
3530 const HttpResponseInfo* response = trans->GetResponseInfo();
3531
3532 EXPECT_FALSE(response == NULL);
3533 EXPECT_EQ(100, response->headers->GetContentLength());
3534 }
3535}
3536
[email protected]1c773ea12009-04-28 19:58:423537TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593538 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403539 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433540 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423541
3542 HttpRequestInfo request;
3543 request.method = "GET";
3544 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433545 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3546 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423547
3548 MockWrite data_writes[] = {
3549 MockWrite("GET / HTTP/1.1\r\n"
3550 "Host: www.google.com\r\n"
3551 "Connection: keep-alive\r\n"
3552 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3553 };
3554
3555 // Lastly, the server responds with the actual content.
3556 MockRead data_reads[] = {
3557 MockRead("HTTP/1.0 200 OK\r\n"),
3558 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3559 MockRead("Content-Length: 100\r\n\r\n"),
3560 MockRead(false, OK),
3561 };
3562
[email protected]31a2bfe2010-02-09 08:03:393563 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3564 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593565 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423566
3567 TestCompletionCallback callback;
3568
[email protected]5a1d7ca2010-04-28 20:12:273569 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423570 EXPECT_EQ(ERR_IO_PENDING, rv);
3571
3572 rv = callback.WaitForResult();
3573 EXPECT_EQ(OK, rv);
3574}
3575
3576TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593577 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403578 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433579 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423580
3581 HttpRequestInfo request;
3582 request.method = "GET";
3583 request.url = GURL("http://www.google.com/");
3584 request.load_flags = 0;
3585 request.referrer = GURL("http://the.previous.site.com/");
3586
3587 MockWrite data_writes[] = {
3588 MockWrite("GET / HTTP/1.1\r\n"
3589 "Host: www.google.com\r\n"
3590 "Connection: keep-alive\r\n"
3591 "Referer: http://the.previous.site.com/\r\n\r\n"),
3592 };
3593
3594 // Lastly, the server responds with the actual content.
3595 MockRead data_reads[] = {
3596 MockRead("HTTP/1.0 200 OK\r\n"),
3597 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3598 MockRead("Content-Length: 100\r\n\r\n"),
3599 MockRead(false, OK),
3600 };
3601
[email protected]31a2bfe2010-02-09 08:03:393602 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3603 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593604 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423605
3606 TestCompletionCallback callback;
3607
[email protected]5a1d7ca2010-04-28 20:12:273608 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423609 EXPECT_EQ(ERR_IO_PENDING, rv);
3610
3611 rv = callback.WaitForResult();
3612 EXPECT_EQ(OK, rv);
3613}
3614
3615TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593616 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403617 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433618 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423619
3620 HttpRequestInfo request;
3621 request.method = "POST";
3622 request.url = GURL("http://www.google.com/");
3623
3624 MockWrite data_writes[] = {
3625 MockWrite("POST / HTTP/1.1\r\n"
3626 "Host: www.google.com\r\n"
3627 "Connection: keep-alive\r\n"
3628 "Content-Length: 0\r\n\r\n"),
3629 };
3630
3631 // Lastly, the server responds with the actual content.
3632 MockRead data_reads[] = {
3633 MockRead("HTTP/1.0 200 OK\r\n"),
3634 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3635 MockRead("Content-Length: 100\r\n\r\n"),
3636 MockRead(false, OK),
3637 };
3638
[email protected]31a2bfe2010-02-09 08:03:393639 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3640 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593641 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423642
3643 TestCompletionCallback callback;
3644
[email protected]5a1d7ca2010-04-28 20:12:273645 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423646 EXPECT_EQ(ERR_IO_PENDING, rv);
3647
3648 rv = callback.WaitForResult();
3649 EXPECT_EQ(OK, rv);
3650}
3651
3652TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593653 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403654 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433655 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423656
3657 HttpRequestInfo request;
3658 request.method = "PUT";
3659 request.url = GURL("http://www.google.com/");
3660
3661 MockWrite data_writes[] = {
3662 MockWrite("PUT / HTTP/1.1\r\n"
3663 "Host: www.google.com\r\n"
3664 "Connection: keep-alive\r\n"
3665 "Content-Length: 0\r\n\r\n"),
3666 };
3667
3668 // Lastly, the server responds with the actual content.
3669 MockRead data_reads[] = {
3670 MockRead("HTTP/1.0 200 OK\r\n"),
3671 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3672 MockRead("Content-Length: 100\r\n\r\n"),
3673 MockRead(false, OK),
3674 };
3675
[email protected]31a2bfe2010-02-09 08:03:393676 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3677 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593678 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423679
3680 TestCompletionCallback callback;
3681
[email protected]5a1d7ca2010-04-28 20:12:273682 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423683 EXPECT_EQ(ERR_IO_PENDING, rv);
3684
3685 rv = callback.WaitForResult();
3686 EXPECT_EQ(OK, rv);
3687}
3688
3689TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593690 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403691 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433692 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423693
3694 HttpRequestInfo request;
3695 request.method = "HEAD";
3696 request.url = GURL("http://www.google.com/");
3697
3698 MockWrite data_writes[] = {
3699 MockWrite("HEAD / HTTP/1.1\r\n"
3700 "Host: www.google.com\r\n"
3701 "Connection: keep-alive\r\n"
3702 "Content-Length: 0\r\n\r\n"),
3703 };
3704
3705 // Lastly, the server responds with the actual content.
3706 MockRead data_reads[] = {
3707 MockRead("HTTP/1.0 200 OK\r\n"),
3708 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3709 MockRead("Content-Length: 100\r\n\r\n"),
3710 MockRead(false, OK),
3711 };
3712
[email protected]31a2bfe2010-02-09 08:03:393713 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3714 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593715 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423716
3717 TestCompletionCallback callback;
3718
[email protected]5a1d7ca2010-04-28 20:12:273719 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423720 EXPECT_EQ(ERR_IO_PENDING, rv);
3721
3722 rv = callback.WaitForResult();
3723 EXPECT_EQ(OK, rv);
3724}
3725
3726TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593727 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403728 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433729 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423730
3731 HttpRequestInfo request;
3732 request.method = "GET";
3733 request.url = GURL("http://www.google.com/");
3734 request.load_flags = LOAD_BYPASS_CACHE;
3735
3736 MockWrite data_writes[] = {
3737 MockWrite("GET / HTTP/1.1\r\n"
3738 "Host: www.google.com\r\n"
3739 "Connection: keep-alive\r\n"
3740 "Pragma: no-cache\r\n"
3741 "Cache-Control: no-cache\r\n\r\n"),
3742 };
3743
3744 // Lastly, the server responds with the actual content.
3745 MockRead data_reads[] = {
3746 MockRead("HTTP/1.0 200 OK\r\n"),
3747 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3748 MockRead("Content-Length: 100\r\n\r\n"),
3749 MockRead(false, OK),
3750 };
3751
[email protected]31a2bfe2010-02-09 08:03:393752 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3753 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593754 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423755
3756 TestCompletionCallback callback;
3757
[email protected]5a1d7ca2010-04-28 20:12:273758 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423759 EXPECT_EQ(ERR_IO_PENDING, rv);
3760
3761 rv = callback.WaitForResult();
3762 EXPECT_EQ(OK, rv);
3763}
3764
3765TEST_F(HttpNetworkTransactionTest,
3766 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593767 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403768 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433769 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423770
3771 HttpRequestInfo request;
3772 request.method = "GET";
3773 request.url = GURL("http://www.google.com/");
3774 request.load_flags = LOAD_VALIDATE_CACHE;
3775
3776 MockWrite data_writes[] = {
3777 MockWrite("GET / HTTP/1.1\r\n"
3778 "Host: www.google.com\r\n"
3779 "Connection: keep-alive\r\n"
3780 "Cache-Control: max-age=0\r\n\r\n"),
3781 };
3782
3783 // Lastly, the server responds with the actual content.
3784 MockRead data_reads[] = {
3785 MockRead("HTTP/1.0 200 OK\r\n"),
3786 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3787 MockRead("Content-Length: 100\r\n\r\n"),
3788 MockRead(false, OK),
3789 };
3790
[email protected]31a2bfe2010-02-09 08:03:393791 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3792 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593793 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423794
3795 TestCompletionCallback callback;
3796
[email protected]5a1d7ca2010-04-28 20:12:273797 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423798 EXPECT_EQ(ERR_IO_PENDING, rv);
3799
3800 rv = callback.WaitForResult();
3801 EXPECT_EQ(OK, rv);
3802}
3803
3804TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593805 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403806 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433807 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423808
3809 HttpRequestInfo request;
3810 request.method = "GET";
3811 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433812 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423813
3814 MockWrite data_writes[] = {
3815 MockWrite("GET / HTTP/1.1\r\n"
3816 "Host: www.google.com\r\n"
3817 "Connection: keep-alive\r\n"
3818 "FooHeader: Bar\r\n\r\n"),
3819 };
3820
3821 // Lastly, the server responds with the actual content.
3822 MockRead data_reads[] = {
3823 MockRead("HTTP/1.0 200 OK\r\n"),
3824 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3825 MockRead("Content-Length: 100\r\n\r\n"),
3826 MockRead(false, OK),
3827 };
3828
[email protected]31a2bfe2010-02-09 08:03:393829 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3830 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593831 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423832
3833 TestCompletionCallback callback;
3834
[email protected]5a1d7ca2010-04-28 20:12:273835 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423836 EXPECT_EQ(ERR_IO_PENDING, rv);
3837
3838 rv = callback.WaitForResult();
3839 EXPECT_EQ(OK, rv);
3840}
3841
[email protected]270c6412010-03-29 22:02:473842TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3843 SessionDependencies session_deps;
3844 scoped_ptr<HttpTransaction> trans(
3845 new HttpNetworkTransaction(CreateSession(&session_deps)));
3846
3847 HttpRequestInfo request;
3848 request.method = "GET";
3849 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433850 request.extra_headers.SetHeader("referer", "www.foo.com");
3851 request.extra_headers.SetHeader("hEllo", "Kitty");
3852 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473853
3854 MockWrite data_writes[] = {
3855 MockWrite("GET / HTTP/1.1\r\n"
3856 "Host: www.google.com\r\n"
3857 "Connection: keep-alive\r\n"
3858 "hEllo: Kitty\r\n"
3859 "FoO: bar\r\n\r\n"),
3860 };
3861
3862 // Lastly, the server responds with the actual content.
3863 MockRead data_reads[] = {
3864 MockRead("HTTP/1.0 200 OK\r\n"),
3865 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3866 MockRead("Content-Length: 100\r\n\r\n"),
3867 MockRead(false, OK),
3868 };
3869
3870 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3871 data_writes, arraysize(data_writes));
3872 session_deps.socket_factory.AddSocketDataProvider(&data);
3873
3874 TestCompletionCallback callback;
3875
[email protected]5a1d7ca2010-04-28 20:12:273876 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473877 EXPECT_EQ(ERR_IO_PENDING, rv);
3878
3879 rv = callback.WaitForResult();
3880 EXPECT_EQ(OK, rv);
3881}
3882
[email protected]3cd17242009-06-23 02:59:023883TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093884 SessionDependencies session_deps(
3885 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023886
3887 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433888 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023889
3890 HttpRequestInfo request;
3891 request.method = "GET";
3892 request.url = GURL("http://www.google.com/");
3893 request.load_flags = 0;
3894
3895 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3896 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3897
3898 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353899 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023900 MockWrite("GET / HTTP/1.1\r\n"
3901 "Host: www.google.com\r\n"
3902 "Connection: keep-alive\r\n\r\n")
3903 };
3904
3905 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593906 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023907 MockRead("HTTP/1.0 200 OK\r\n"),
3908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3909 MockRead("Payload"),
3910 MockRead(false, OK)
3911 };
3912
[email protected]31a2bfe2010-02-09 08:03:393913 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3914 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593915 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023916
3917 TestCompletionCallback callback;
3918
[email protected]5a1d7ca2010-04-28 20:12:273919 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023920 EXPECT_EQ(ERR_IO_PENDING, rv);
3921
3922 rv = callback.WaitForResult();
3923 EXPECT_EQ(OK, rv);
3924
3925 const HttpResponseInfo* response = trans->GetResponseInfo();
3926 EXPECT_FALSE(response == NULL);
3927
3928 std::string response_text;
3929 rv = ReadTransaction(trans.get(), &response_text);
3930 EXPECT_EQ(OK, rv);
3931 EXPECT_EQ("Payload", response_text);
3932}
3933
3934TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093935 SessionDependencies session_deps(
3936 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023937
3938 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433939 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023940
3941 HttpRequestInfo request;
3942 request.method = "GET";
3943 request.url = GURL("https://www.google.com/");
3944 request.load_flags = 0;
3945
3946 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3947 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3948
3949 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353950 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3951 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023952 MockWrite("GET / HTTP/1.1\r\n"
3953 "Host: www.google.com\r\n"
3954 "Connection: keep-alive\r\n\r\n")
3955 };
3956
3957 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353958 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3959 arraysize(read_buffer)),
3960 MockRead("HTTP/1.0 200 OK\r\n"),
3961 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3962 MockRead("Payload"),
3963 MockRead(false, OK)
3964 };
3965
[email protected]31a2bfe2010-02-09 08:03:393966 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3967 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593968 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353969
[email protected]5ecc992a42009-11-11 01:41:593970 SSLSocketDataProvider ssl(true, OK);
3971 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353972
3973 TestCompletionCallback callback;
3974
[email protected]5a1d7ca2010-04-28 20:12:273975 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353976 EXPECT_EQ(ERR_IO_PENDING, rv);
3977
3978 rv = callback.WaitForResult();
3979 EXPECT_EQ(OK, rv);
3980
3981 const HttpResponseInfo* response = trans->GetResponseInfo();
3982 EXPECT_FALSE(response == NULL);
3983
3984 std::string response_text;
3985 rv = ReadTransaction(trans.get(), &response_text);
3986 EXPECT_EQ(OK, rv);
3987 EXPECT_EQ("Payload", response_text);
3988}
3989
3990TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093991 SessionDependencies session_deps(
3992 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353993
3994 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433995 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353996
3997 HttpRequestInfo request;
3998 request.method = "GET";
3999 request.url = GURL("http://www.google.com/");
4000 request.load_flags = 0;
4001
4002 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4003 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374004 const char kSOCKS5OkRequest[] = {
4005 0x05, // Version
4006 0x01, // Command (CONNECT)
4007 0x00, // Reserved.
4008 0x03, // Address type (DOMAINNAME).
4009 0x0E, // Length of domain (14)
4010 // Domain string:
4011 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4012 0x00, 0x50, // 16-bit port (80)
4013 };
[email protected]e0c27be2009-07-15 13:09:354014 const char kSOCKS5OkResponse[] =
4015 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4016
4017 MockWrite data_writes[] = {
4018 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4019 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4020 MockWrite("GET / HTTP/1.1\r\n"
4021 "Host: www.google.com\r\n"
4022 "Connection: keep-alive\r\n\r\n")
4023 };
4024
4025 MockRead data_reads[] = {
4026 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4027 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4028 MockRead("HTTP/1.0 200 OK\r\n"),
4029 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4030 MockRead("Payload"),
4031 MockRead(false, OK)
4032 };
4033
[email protected]31a2bfe2010-02-09 08:03:394034 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4035 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594036 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354037
4038 TestCompletionCallback callback;
4039
[email protected]5a1d7ca2010-04-28 20:12:274040 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354041 EXPECT_EQ(ERR_IO_PENDING, rv);
4042
4043 rv = callback.WaitForResult();
4044 EXPECT_EQ(OK, rv);
4045
4046 const HttpResponseInfo* response = trans->GetResponseInfo();
4047 EXPECT_FALSE(response == NULL);
4048
4049 std::string response_text;
4050 rv = ReadTransaction(trans.get(), &response_text);
4051 EXPECT_EQ(OK, rv);
4052 EXPECT_EQ("Payload", response_text);
4053}
4054
4055TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094056 SessionDependencies session_deps(
4057 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354058
4059 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434060 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354061
4062 HttpRequestInfo request;
4063 request.method = "GET";
4064 request.url = GURL("https://www.google.com/");
4065 request.load_flags = 0;
4066
4067 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4068 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374069 const unsigned char kSOCKS5OkRequest[] = {
4070 0x05, // Version
4071 0x01, // Command (CONNECT)
4072 0x00, // Reserved.
4073 0x03, // Address type (DOMAINNAME).
4074 0x0E, // Length of domain (14)
4075 // Domain string:
4076 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4077 0x01, 0xBB, // 16-bit port (443)
4078 };
4079
[email protected]e0c27be2009-07-15 13:09:354080 const char kSOCKS5OkResponse[] =
4081 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4082
4083 MockWrite data_writes[] = {
4084 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4085 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4086 arraysize(kSOCKS5OkRequest)),
4087 MockWrite("GET / HTTP/1.1\r\n"
4088 "Host: www.google.com\r\n"
4089 "Connection: keep-alive\r\n\r\n")
4090 };
4091
4092 MockRead data_reads[] = {
4093 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4094 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024095 MockRead("HTTP/1.0 200 OK\r\n"),
4096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4097 MockRead("Payload"),
4098 MockRead(false, OK)
4099 };
4100
[email protected]31a2bfe2010-02-09 08:03:394101 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4102 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594103 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024104
[email protected]5ecc992a42009-11-11 01:41:594105 SSLSocketDataProvider ssl(true, OK);
4106 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024107
4108 TestCompletionCallback callback;
4109
[email protected]5a1d7ca2010-04-28 20:12:274110 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024111 EXPECT_EQ(ERR_IO_PENDING, rv);
4112
4113 rv = callback.WaitForResult();
4114 EXPECT_EQ(OK, rv);
4115
4116 const HttpResponseInfo* response = trans->GetResponseInfo();
4117 EXPECT_FALSE(response == NULL);
4118
4119 std::string response_text;
4120 rv = ReadTransaction(trans.get(), &response_text);
4121 EXPECT_EQ(OK, rv);
4122 EXPECT_EQ("Payload", response_text);
4123}
4124
[email protected]04e5be32009-06-26 20:00:314125// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064126
4127struct GroupNameTest {
4128 std::string proxy_server;
4129 std::string url;
4130 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184131 bool ssl;
[email protected]2d731a32010-04-29 01:04:064132};
4133
4134scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4135 const std::string& proxy_server) {
4136 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4137 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4138
4139 HttpAlternateProtocols* alternate_protocols =
4140 session->mutable_alternate_protocols();
4141 alternate_protocols->SetAlternateProtocolFor(
4142 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354143 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064144
4145 return session;
4146}
4147
4148int GroupNameTransactionHelper(
4149 const std::string& url,
4150 const scoped_refptr<HttpNetworkSession>& session) {
4151 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4152
4153 HttpRequestInfo request;
4154 request.method = "GET";
4155 request.url = GURL(url);
4156 request.load_flags = 0;
4157
4158 TestCompletionCallback callback;
4159
4160 // We do not complete this request, the dtor will clean the transaction up.
4161 return trans->Start(&request, &callback, BoundNetLog());
4162}
4163
4164TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4165 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314166 {
[email protected]2d731a32010-04-29 01:04:064167 "", // unused
[email protected]04e5be32009-06-26 20:00:314168 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544169 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184170 false,
[email protected]2ff8b312010-04-26 22:20:544171 },
4172 {
[email protected]2d731a32010-04-29 01:04:064173 "", // unused
[email protected]2ff8b312010-04-26 22:20:544174 "http://[2001:1418:13:1::25]/direct",
4175 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184176 false,
[email protected]04e5be32009-06-26 20:00:314177 },
[email protected]04e5be32009-06-26 20:00:314178
4179 // SSL Tests
4180 {
[email protected]2d731a32010-04-29 01:04:064181 "", // unused
[email protected]04e5be32009-06-26 20:00:314182 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024183 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184184 true,
[email protected]04e5be32009-06-26 20:00:314185 },
4186 {
[email protected]2d731a32010-04-29 01:04:064187 "", // unused
4188 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024189 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184190 true,
[email protected]04e5be32009-06-26 20:00:314191 },
4192 {
[email protected]2d731a32010-04-29 01:04:064193 "", // unused
[email protected]2ff8b312010-04-26 22:20:544194 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024195 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184196 true,
[email protected]2ff8b312010-04-26 22:20:544197 },
[email protected]2d731a32010-04-29 01:04:064198 };
[email protected]2ff8b312010-04-26 22:20:544199
[email protected]2d731a32010-04-29 01:04:064200 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4201
4202 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4203 scoped_refptr<HttpNetworkSession> session(
4204 SetupSessionForGroupNameTests(tests[i].proxy_server));
4205
4206 HttpNetworkSessionPeer peer(session);
4207 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4208 new CaptureGroupNameTCPSocketPool(session.get()));
4209 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184210 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4211 new CaptureGroupNameSSLSocketPool(session.get()));
4212 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064213
4214 EXPECT_EQ(ERR_IO_PENDING,
4215 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184216 if (tests[i].ssl)
4217 EXPECT_EQ(tests[i].expected_group_name,
4218 ssl_conn_pool->last_group_name_received());
4219 else
4220 EXPECT_EQ(tests[i].expected_group_name,
4221 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064222 }
4223
4224 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4225}
4226
4227TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4228 const GroupNameTest tests[] = {
4229 {
4230 "http_proxy",
4231 "http://www.google.com/http_proxy_normal",
4232 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184233 false,
[email protected]2d731a32010-04-29 01:04:064234 },
4235
4236 // SSL Tests
4237 {
4238 "http_proxy",
4239 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024240 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184241 true,
[email protected]2d731a32010-04-29 01:04:064242 },
4243
[email protected]9faeded92010-04-29 20:03:054244 {
4245 "http_proxy",
4246 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024247 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184248 true,
[email protected]9faeded92010-04-29 20:03:054249 },
[email protected]2d731a32010-04-29 01:04:064250 };
4251
4252 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4253
4254 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4255 scoped_refptr<HttpNetworkSession> session(
4256 SetupSessionForGroupNameTests(tests[i].proxy_server));
4257
4258 HttpNetworkSessionPeer peer(session);
4259
[email protected]e60e47a2010-07-14 03:37:184260 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134261 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4262 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184263 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4264 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4265 new CaptureGroupNameSSLSocketPool(session.get()));
4266 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064267
4268 EXPECT_EQ(ERR_IO_PENDING,
4269 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184270 if (tests[i].ssl)
4271 EXPECT_EQ(tests[i].expected_group_name,
4272 ssl_conn_pool->last_group_name_received());
4273 else
4274 EXPECT_EQ(tests[i].expected_group_name,
4275 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064276 }
4277
4278 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4279}
4280
4281TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4282 const GroupNameTest tests[] = {
4283 {
4284 "socks4://socks_proxy:1080",
4285 "http://www.google.com/socks4_direct",
4286 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184287 false,
[email protected]2d731a32010-04-29 01:04:064288 },
4289 {
4290 "socks5://socks_proxy:1080",
4291 "http://www.google.com/socks5_direct",
4292 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184293 false,
[email protected]2d731a32010-04-29 01:04:064294 },
4295
4296 // SSL Tests
4297 {
4298 "socks4://socks_proxy:1080",
4299 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024300 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184301 true,
[email protected]2d731a32010-04-29 01:04:064302 },
4303 {
4304 "socks5://socks_proxy:1080",
4305 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024306 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184307 true,
[email protected]2d731a32010-04-29 01:04:064308 },
4309
[email protected]9faeded92010-04-29 20:03:054310 {
4311 "socks4://socks_proxy:1080",
4312 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024313 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184314 true,
[email protected]9faeded92010-04-29 20:03:054315 },
[email protected]04e5be32009-06-26 20:00:314316 };
4317
[email protected]2ff8b312010-04-26 22:20:544318 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4319
[email protected]04e5be32009-06-26 20:00:314320 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064321 scoped_refptr<HttpNetworkSession> session(
4322 SetupSessionForGroupNameTests(tests[i].proxy_server));
4323 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314324
[email protected]e60e47a2010-07-14 03:37:184325 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264326 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064327 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184328 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4329 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4330 new CaptureGroupNameSSLSocketPool(session.get()));
4331 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314332
[email protected]5695b8c2009-09-30 21:36:434333 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314334
[email protected]2d731a32010-04-29 01:04:064335 EXPECT_EQ(ERR_IO_PENDING,
4336 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184337 if (tests[i].ssl)
4338 EXPECT_EQ(tests[i].expected_group_name,
4339 ssl_conn_pool->last_group_name_received());
4340 else
4341 EXPECT_EQ(tests[i].expected_group_name,
4342 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314343 }
[email protected]2ff8b312010-04-26 22:20:544344
4345 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314346}
4347
[email protected]9172a982009-06-06 00:30:254348TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544349 SessionDependencies session_deps(
4350 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324351
[email protected]69719062010-01-05 20:09:214352 // This simulates failure resolving all hostnames; that means we will fail
4353 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324354 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4355
[email protected]9172a982009-06-06 00:30:254356 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434357 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254358
4359 HttpRequestInfo request;
4360 request.method = "GET";
4361 request.url = GURL("http://www.google.com/");
4362
4363 TestCompletionCallback callback;
4364
[email protected]5a1d7ca2010-04-28 20:12:274365 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254366 EXPECT_EQ(ERR_IO_PENDING, rv);
4367
[email protected]9172a982009-06-06 00:30:254368 rv = callback.WaitForResult();
4369 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4370}
4371
[email protected]f3e6c1e2009-06-15 20:52:124372// Host resolution observer used by
4373// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4374// resovle requests are issued with a referrer of |expected_referrer|.
4375class ResolutionReferrerObserver : public HostResolver::Observer {
4376 public:
4377 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4378 : expected_referrer_(expected_referrer),
4379 called_start_with_referrer_(false),
4380 called_finish_with_referrer_(false) {
4381 }
4382
4383 virtual void OnStartResolution(int id,
4384 const HostResolver::RequestInfo& info) {
4385 if (info.referrer() == expected_referrer_)
4386 called_start_with_referrer_ = true;
4387 }
4388
4389 virtual void OnFinishResolutionWithStatus(
4390 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4391 if (info.referrer() == expected_referrer_)
4392 called_finish_with_referrer_ = true;
4393 }
4394
[email protected]eb255d32009-06-17 02:11:034395 virtual void OnCancelResolution(int id,
4396 const HostResolver::RequestInfo& info ) {
4397 FAIL() << "Should not be cancelling any requests!";
4398 }
4399
[email protected]f3e6c1e2009-06-15 20:52:124400 bool did_complete_with_expected_referrer() const {
4401 return called_start_with_referrer_ && called_finish_with_referrer_;
4402 }
4403
4404 private:
4405 GURL expected_referrer_;
4406 bool called_start_with_referrer_;
4407 bool called_finish_with_referrer_;
4408
4409 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4410};
4411
4412// Make sure that when HostResolver::Resolve() is invoked, it passes through
4413// the "referrer". This is depended on by the DNS prefetch observer.
4414TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4415 GURL referrer = GURL("http://expected-referrer/");
4416 EXPECT_TRUE(referrer.is_valid());
4417 ResolutionReferrerObserver resolution_observer(referrer);
4418
4419 SessionDependencies session_deps;
4420 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434421 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124422
4423 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144424 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124425
4426 // Connect up a mock socket which will fail when reading.
4427 MockRead data_reads[] = {
4428 MockRead(false, ERR_FAILED),
4429 };
[email protected]31a2bfe2010-02-09 08:03:394430 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594431 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124432
4433 // Issue a request, containing an HTTP referrer.
4434 HttpRequestInfo request;
4435 request.method = "GET";
4436 request.referrer = referrer;
4437 request.url = GURL("http://www.google.com/");
4438
4439 // Run the request until it fails reading from the socket.
4440 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274441 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124442 EXPECT_EQ(ERR_IO_PENDING, rv);
4443 rv = callback.WaitForResult();
4444 EXPECT_EQ(ERR_FAILED, rv);
4445
4446 // Check that the host resolution observer saw |referrer|.
4447 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4448}
4449
[email protected]685af592010-05-11 19:31:244450// Base test to make sure that when the load flags for a request specify to
4451// bypass the cache, the DNS cache is not used.
4452void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284453 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324454
[email protected]a2c2fb92009-07-18 07:31:044455 // Select a host resolver that does caching.
4456 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324457
[email protected]3b9cca42009-06-16 01:08:284458 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434459 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284460
4461 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4462 // a synchronous lookup.)
4463 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144464 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464465 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274466 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284467 EXPECT_EQ(OK, rv);
4468
4469 // Verify that it was added to host cache, by doing a subsequent async lookup
4470 // and confirming it completes synchronously.
4471 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464472 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284473 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274474 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324475 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284476
4477 // Inject a failure the next time that "www.google.com" is resolved. This way
4478 // we can tell if the next lookup hit the cache, or the "network".
4479 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324480 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284481
4482 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4483 // first read -- this won't be reached as the host resolution will fail first.
4484 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394485 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594486 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284487
4488 // Issue a request, asking to bypass the cache(s).
4489 HttpRequestInfo request;
4490 request.method = "GET";
[email protected]685af592010-05-11 19:31:244491 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284492 request.url = GURL("http://www.google.com/");
4493
4494 // Run the request.
4495 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274496 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284497 ASSERT_EQ(ERR_IO_PENDING, rv);
4498 rv = callback.WaitForResult();
4499
4500 // If we bypassed the cache, we would have gotten a failure while resolving
4501 // "www.google.com".
4502 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4503}
4504
[email protected]685af592010-05-11 19:31:244505// There are multiple load flags that should trigger the host cache bypass.
4506// Test each in isolation:
4507TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4508 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4509}
4510
4511TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4512 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4513}
4514
4515TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4516 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4517}
4518
[email protected]0877e3d2009-10-17 22:29:574519// Make sure we can handle an error when writing the request.
4520TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4521 SessionDependencies session_deps;
4522 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4523
4524 HttpRequestInfo request;
4525 request.method = "GET";
4526 request.url = GURL("http://www.foo.com/");
4527 request.load_flags = 0;
4528
4529 MockWrite write_failure[] = {
4530 MockWrite(true, ERR_CONNECTION_RESET),
4531 };
[email protected]31a2bfe2010-02-09 08:03:394532 StaticSocketDataProvider data(NULL, 0,
4533 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594534 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574535
4536 TestCompletionCallback callback;
4537
4538 scoped_ptr<HttpTransaction> trans(
4539 new HttpNetworkTransaction(CreateSession(&session_deps)));
4540
[email protected]5a1d7ca2010-04-28 20:12:274541 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574542 EXPECT_EQ(ERR_IO_PENDING, rv);
4543
4544 rv = callback.WaitForResult();
4545 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4546}
4547
4548// Check that a connection closed after the start of the headers finishes ok.
4549TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4550 SessionDependencies session_deps;
4551 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4552
4553 HttpRequestInfo request;
4554 request.method = "GET";
4555 request.url = GURL("http://www.foo.com/");
4556 request.load_flags = 0;
4557
4558 MockRead data_reads[] = {
4559 MockRead("HTTP/1."),
4560 MockRead(false, OK),
4561 };
4562
[email protected]31a2bfe2010-02-09 08:03:394563 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594564 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574565
4566 TestCompletionCallback callback;
4567
4568 scoped_ptr<HttpTransaction> trans(
4569 new HttpNetworkTransaction(CreateSession(&session_deps)));
4570
[email protected]5a1d7ca2010-04-28 20:12:274571 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574572 EXPECT_EQ(ERR_IO_PENDING, rv);
4573
4574 rv = callback.WaitForResult();
4575 EXPECT_EQ(OK, rv);
4576
4577 const HttpResponseInfo* response = trans->GetResponseInfo();
4578 EXPECT_TRUE(response != NULL);
4579
4580 EXPECT_TRUE(response->headers != NULL);
4581 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4582
4583 std::string response_data;
4584 rv = ReadTransaction(trans.get(), &response_data);
4585 EXPECT_EQ(OK, rv);
4586 EXPECT_EQ("", response_data);
4587}
4588
4589// Make sure that a dropped connection while draining the body for auth
4590// restart does the right thing.
4591TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4592 SessionDependencies session_deps;
4593 scoped_ptr<HttpTransaction> trans(
4594 new HttpNetworkTransaction(CreateSession(&session_deps)));
4595
4596 HttpRequestInfo request;
4597 request.method = "GET";
4598 request.url = GURL("http://www.google.com/");
4599 request.load_flags = 0;
4600
4601 MockWrite data_writes1[] = {
4602 MockWrite("GET / HTTP/1.1\r\n"
4603 "Host: www.google.com\r\n"
4604 "Connection: keep-alive\r\n\r\n"),
4605 };
4606
4607 MockRead data_reads1[] = {
4608 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4609 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4610 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4611 MockRead("Content-Length: 14\r\n\r\n"),
4612 MockRead("Unauth"),
4613 MockRead(true, ERR_CONNECTION_RESET),
4614 };
4615
[email protected]31a2bfe2010-02-09 08:03:394616 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4617 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594618 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574619
4620 // After calling trans->RestartWithAuth(), this is the request we should
4621 // be issuing -- the final header line contains the credentials.
4622 MockWrite data_writes2[] = {
4623 MockWrite("GET / HTTP/1.1\r\n"
4624 "Host: www.google.com\r\n"
4625 "Connection: keep-alive\r\n"
4626 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4627 };
4628
4629 // Lastly, the server responds with the actual content.
4630 MockRead data_reads2[] = {
4631 MockRead("HTTP/1.1 200 OK\r\n"),
4632 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4633 MockRead("Content-Length: 100\r\n\r\n"),
4634 MockRead(false, OK),
4635 };
4636
[email protected]31a2bfe2010-02-09 08:03:394637 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4638 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594639 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574640
4641 TestCompletionCallback callback1;
4642
[email protected]5a1d7ca2010-04-28 20:12:274643 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574644 EXPECT_EQ(ERR_IO_PENDING, rv);
4645
4646 rv = callback1.WaitForResult();
4647 EXPECT_EQ(OK, rv);
4648
4649 const HttpResponseInfo* response = trans->GetResponseInfo();
4650 EXPECT_FALSE(response == NULL);
4651
4652 // The password prompt info should have been set in response->auth_challenge.
4653 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4654
4655 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4656 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4657 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4658
4659 TestCompletionCallback callback2;
4660
[email protected]13c8a092010-07-29 06:15:444661 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:574662 EXPECT_EQ(ERR_IO_PENDING, rv);
4663
4664 rv = callback2.WaitForResult();
4665 EXPECT_EQ(OK, rv);
4666
4667 response = trans->GetResponseInfo();
4668 EXPECT_FALSE(response == NULL);
4669 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4670 EXPECT_EQ(100, response->headers->GetContentLength());
4671}
4672
4673// Test HTTPS connections going through a proxy that sends extra data.
4674TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4675 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4676
4677 HttpRequestInfo request;
4678 request.method = "GET";
4679 request.url = GURL("https://www.google.com/");
4680 request.load_flags = 0;
4681
4682 MockRead proxy_reads[] = {
4683 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4684 MockRead(false, OK)
4685 };
4686
[email protected]31a2bfe2010-02-09 08:03:394687 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594688 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574689
[email protected]5ecc992a42009-11-11 01:41:594690 session_deps.socket_factory.AddSocketDataProvider(&data);
4691 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574692
4693 TestCompletionCallback callback;
4694
4695 session_deps.socket_factory.ResetNextMockIndexes();
4696
4697 scoped_ptr<HttpTransaction> trans(
4698 new HttpNetworkTransaction(CreateSession(&session_deps)));
4699
[email protected]5a1d7ca2010-04-28 20:12:274700 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574701 EXPECT_EQ(ERR_IO_PENDING, rv);
4702
4703 rv = callback.WaitForResult();
4704 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4705}
4706
[email protected]e22e1362009-11-23 21:31:124707TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464708 SessionDependencies session_deps;
4709 scoped_ptr<HttpTransaction> trans(
4710 new HttpNetworkTransaction(CreateSession(&session_deps)));
4711
4712 HttpRequestInfo request;
4713 request.method = "GET";
4714 request.url = GURL("http://www.google.com/");
4715 request.load_flags = 0;
4716
[email protected]e22e1362009-11-23 21:31:124717 MockRead data_reads[] = {
4718 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4719 MockRead(false, OK),
4720 };
[email protected]9492e4a2010-02-24 00:58:464721
4722 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4723 session_deps.socket_factory.AddSocketDataProvider(&data);
4724
4725 TestCompletionCallback callback;
4726
[email protected]5a1d7ca2010-04-28 20:12:274727 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464728 EXPECT_EQ(ERR_IO_PENDING, rv);
4729
4730 EXPECT_EQ(OK, callback.WaitForResult());
4731
4732 const HttpResponseInfo* response = trans->GetResponseInfo();
4733 EXPECT_TRUE(response != NULL);
4734
4735 EXPECT_TRUE(response->headers != NULL);
4736 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4737
4738 std::string response_data;
4739 rv = ReadTransaction(trans.get(), &response_data);
4740 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124741}
4742
[email protected]95d88ffe2010-02-04 21:25:334743TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4744 SessionDependencies session_deps;
4745 scoped_ptr<HttpTransaction> trans(
4746 new HttpNetworkTransaction(CreateSession(&session_deps)));
4747
4748 HttpRequestInfo request;
4749 request.method = "POST";
4750 request.url = GURL("http://www.google.com/upload");
4751 request.upload_data = new UploadData;
4752 request.load_flags = 0;
4753
4754 FilePath temp_file_path;
4755 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4756 const uint64 kFakeSize = 100000; // file is actually blank
4757
4758 std::vector<UploadData::Element> elements;
4759 UploadData::Element element;
4760 element.SetToFilePath(temp_file_path);
4761 element.SetContentLength(kFakeSize);
4762 elements.push_back(element);
4763 request.upload_data->set_elements(elements);
4764 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4765
4766 MockRead data_reads[] = {
4767 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4768 MockRead("hello world"),
4769 MockRead(false, OK),
4770 };
[email protected]31a2bfe2010-02-09 08:03:394771 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334772 session_deps.socket_factory.AddSocketDataProvider(&data);
4773
4774 TestCompletionCallback callback;
4775
[email protected]5a1d7ca2010-04-28 20:12:274776 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334777 EXPECT_EQ(ERR_IO_PENDING, rv);
4778
4779 rv = callback.WaitForResult();
4780 EXPECT_EQ(OK, rv);
4781
4782 const HttpResponseInfo* response = trans->GetResponseInfo();
4783 EXPECT_TRUE(response != NULL);
4784
4785 EXPECT_TRUE(response->headers != NULL);
4786 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4787
4788 std::string response_data;
4789 rv = ReadTransaction(trans.get(), &response_data);
4790 EXPECT_EQ(OK, rv);
4791 EXPECT_EQ("hello world", response_data);
4792
4793 file_util::Delete(temp_file_path, false);
4794}
4795
[email protected]6624b4622010-03-29 19:58:364796TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4797 // If we try to upload an unreadable file, the network stack should report
4798 // the file size as zero and upload zero bytes for that file.
4799 SessionDependencies session_deps;
4800 scoped_ptr<HttpTransaction> trans(
4801 new HttpNetworkTransaction(CreateSession(&session_deps)));
4802
4803 FilePath temp_file;
4804 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4805 std::string temp_file_content("Unreadable file.");
4806 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4807 temp_file_content.length()));
4808 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4809
4810 HttpRequestInfo request;
4811 request.method = "POST";
4812 request.url = GURL("http://www.google.com/upload");
4813 request.upload_data = new UploadData;
4814 request.load_flags = 0;
4815
4816 std::vector<UploadData::Element> elements;
4817 UploadData::Element element;
4818 element.SetToFilePath(temp_file);
4819 elements.push_back(element);
4820 request.upload_data->set_elements(elements);
4821
4822 MockRead data_reads[] = {
4823 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4824 MockRead(false, OK),
4825 };
4826 MockWrite data_writes[] = {
4827 MockWrite("POST /upload HTTP/1.1\r\n"
4828 "Host: www.google.com\r\n"
4829 "Connection: keep-alive\r\n"
4830 "Content-Length: 0\r\n\r\n"),
4831 MockWrite(false, OK),
4832 };
4833 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4834 arraysize(data_writes));
4835 session_deps.socket_factory.AddSocketDataProvider(&data);
4836
4837 TestCompletionCallback callback;
4838
[email protected]5a1d7ca2010-04-28 20:12:274839 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364840 EXPECT_EQ(ERR_IO_PENDING, rv);
4841
4842 rv = callback.WaitForResult();
4843 EXPECT_EQ(OK, rv);
4844
4845 const HttpResponseInfo* response = trans->GetResponseInfo();
4846 EXPECT_TRUE(response != NULL);
4847 EXPECT_TRUE(response->headers != NULL);
4848 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4849
4850 file_util::Delete(temp_file, false);
4851}
4852
4853TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4854 SessionDependencies session_deps;
4855 scoped_ptr<HttpTransaction> trans(
4856 new HttpNetworkTransaction(CreateSession(&session_deps)));
4857
4858 FilePath temp_file;
4859 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4860 std::string temp_file_contents("Unreadable file.");
4861 std::string unreadable_contents(temp_file_contents.length(), '\0');
4862 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4863 temp_file_contents.length()));
4864
4865 HttpRequestInfo request;
4866 request.method = "POST";
4867 request.url = GURL("http://www.google.com/upload");
4868 request.upload_data = new UploadData;
4869 request.load_flags = 0;
4870
4871 std::vector<UploadData::Element> elements;
4872 UploadData::Element element;
4873 element.SetToFilePath(temp_file);
4874 elements.push_back(element);
4875 request.upload_data->set_elements(elements);
4876
4877 MockRead data_reads[] = {
4878 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4879 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4880 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4881
4882 MockRead("HTTP/1.1 200 OK\r\n"),
4883 MockRead("Content-Length: 0\r\n\r\n"),
4884 MockRead(false, OK),
4885 };
4886 MockWrite data_writes[] = {
4887 MockWrite("POST /upload HTTP/1.1\r\n"
4888 "Host: www.google.com\r\n"
4889 "Connection: keep-alive\r\n"
4890 "Content-Length: 16\r\n\r\n"),
4891 MockWrite(false, temp_file_contents.c_str()),
4892
4893 MockWrite("POST /upload HTTP/1.1\r\n"
4894 "Host: www.google.com\r\n"
4895 "Connection: keep-alive\r\n"
4896 "Content-Length: 16\r\n"
4897 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4898 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4899 MockWrite(false, OK),
4900 };
4901 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4902 arraysize(data_writes));
4903 session_deps.socket_factory.AddSocketDataProvider(&data);
4904
4905 TestCompletionCallback callback1;
4906
[email protected]5a1d7ca2010-04-28 20:12:274907 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364908 EXPECT_EQ(ERR_IO_PENDING, rv);
4909
4910 rv = callback1.WaitForResult();
4911 EXPECT_EQ(OK, rv);
4912
4913 const HttpResponseInfo* response = trans->GetResponseInfo();
4914 EXPECT_TRUE(response != NULL);
4915 EXPECT_TRUE(response->headers != NULL);
4916 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4917
4918 // The password prompt info should have been set in response->auth_challenge.
4919 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4920 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4921 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4922 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4923
4924 // Now make the file unreadable and try again.
4925 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4926
4927 TestCompletionCallback callback2;
4928
[email protected]13c8a092010-07-29 06:15:444929 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:364930 EXPECT_EQ(ERR_IO_PENDING, rv);
4931
4932 rv = callback2.WaitForResult();
4933 EXPECT_EQ(OK, rv);
4934
4935 response = trans->GetResponseInfo();
4936 EXPECT_TRUE(response != NULL);
4937 EXPECT_TRUE(response->headers != NULL);
4938 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4939 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4940
4941 file_util::Delete(temp_file, false);
4942}
4943
[email protected]aeefc9e82010-02-19 16:18:274944// Tests that changes to Auth realms are treated like auth rejections.
4945TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4946 SessionDependencies session_deps;
4947 scoped_ptr<HttpTransaction> trans(
4948 new HttpNetworkTransaction(CreateSession(&session_deps)));
4949
4950 HttpRequestInfo request;
4951 request.method = "GET";
4952 request.url = GURL("http://www.google.com/");
4953 request.load_flags = 0;
4954
4955 // First transaction will request a resource and receive a Basic challenge
4956 // with realm="first_realm".
4957 MockWrite data_writes1[] = {
4958 MockWrite("GET / HTTP/1.1\r\n"
4959 "Host: www.google.com\r\n"
4960 "Connection: keep-alive\r\n"
4961 "\r\n"),
4962 };
4963 MockRead data_reads1[] = {
4964 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4965 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4966 "\r\n"),
4967 };
4968
4969 // After calling trans->RestartWithAuth(), provide an Authentication header
4970 // for first_realm. The server will reject and provide a challenge with
4971 // second_realm.
4972 MockWrite data_writes2[] = {
4973 MockWrite("GET / HTTP/1.1\r\n"
4974 "Host: www.google.com\r\n"
4975 "Connection: keep-alive\r\n"
4976 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4977 "\r\n"),
4978 };
4979 MockRead data_reads2[] = {
4980 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4981 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4982 "\r\n"),
4983 };
4984
4985 // This again fails, and goes back to first_realm. Make sure that the
4986 // entry is removed from cache.
4987 MockWrite data_writes3[] = {
4988 MockWrite("GET / HTTP/1.1\r\n"
4989 "Host: www.google.com\r\n"
4990 "Connection: keep-alive\r\n"
4991 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4992 "\r\n"),
4993 };
4994 MockRead data_reads3[] = {
4995 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4996 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4997 "\r\n"),
4998 };
4999
5000 // Try one last time (with the correct password) and get the resource.
5001 MockWrite data_writes4[] = {
5002 MockWrite("GET / HTTP/1.1\r\n"
5003 "Host: www.google.com\r\n"
5004 "Connection: keep-alive\r\n"
5005 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5006 "\r\n"),
5007 };
5008 MockRead data_reads4[] = {
5009 MockRead("HTTP/1.1 200 OK\r\n"
5010 "Content-Type: text/html; charset=iso-8859-1\r\n"
5011 "Content-Length: 100\r\n"
5012 "\r\n"),
5013 };
5014
5015 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5016 data_writes1, arraysize(data_writes1));
5017 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5018 data_writes2, arraysize(data_writes2));
5019 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5020 data_writes3, arraysize(data_writes3));
5021 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5022 data_writes4, arraysize(data_writes4));
5023 session_deps.socket_factory.AddSocketDataProvider(&data1);
5024 session_deps.socket_factory.AddSocketDataProvider(&data2);
5025 session_deps.socket_factory.AddSocketDataProvider(&data3);
5026 session_deps.socket_factory.AddSocketDataProvider(&data4);
5027
5028 TestCompletionCallback callback1;
5029
5030 // Issue the first request with Authorize headers. There should be a
5031 // password prompt for first_realm waiting to be filled in after the
5032 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275033 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275034 EXPECT_EQ(ERR_IO_PENDING, rv);
5035 rv = callback1.WaitForResult();
5036 EXPECT_EQ(OK, rv);
5037 const HttpResponseInfo* response = trans->GetResponseInfo();
5038 ASSERT_FALSE(response == NULL);
5039 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5040 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5041 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5042 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5043
5044 // Issue the second request with an incorrect password. There should be a
5045 // password prompt for second_realm waiting to be filled in after the
5046 // transaction completes.
5047 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445048 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275049 EXPECT_EQ(ERR_IO_PENDING, rv);
5050 rv = callback2.WaitForResult();
5051 EXPECT_EQ(OK, rv);
5052 response = trans->GetResponseInfo();
5053 ASSERT_FALSE(response == NULL);
5054 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5055 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5056 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5057 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5058
5059 // Issue the third request with another incorrect password. There should be
5060 // a password prompt for first_realm waiting to be filled in. If the password
5061 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5062 // first_realm was not correctly removed.
5063 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445064 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275065 EXPECT_EQ(ERR_IO_PENDING, rv);
5066 rv = callback3.WaitForResult();
5067 EXPECT_EQ(OK, rv);
5068 response = trans->GetResponseInfo();
5069 ASSERT_FALSE(response == NULL);
5070 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5071 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5072 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5073 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5074
5075 // Issue the fourth request with the correct password and username.
5076 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445077 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275078 EXPECT_EQ(ERR_IO_PENDING, rv);
5079 rv = callback4.WaitForResult();
5080 EXPECT_EQ(OK, rv);
5081 response = trans->GetResponseInfo();
5082 ASSERT_FALSE(response == NULL);
5083 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5084}
5085
[email protected]564b4912010-03-09 16:30:425086TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:425087 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:065088 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:425089
[email protected]564b4912010-03-09 16:30:425090 SessionDependencies session_deps;
5091
5092 MockRead data_reads[] = {
5093 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355094 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425095 MockRead("hello world"),
5096 MockRead(false, OK),
5097 };
5098
5099 HttpRequestInfo request;
5100 request.method = "GET";
5101 request.url = GURL("http://www.google.com/");
5102 request.load_flags = 0;
5103
5104 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5105
5106 session_deps.socket_factory.AddSocketDataProvider(&data);
5107
5108 TestCompletionCallback callback;
5109
5110 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5111 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5112
[email protected]5a1d7ca2010-04-28 20:12:275113 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425114 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535115
[email protected]2fbaecf22010-07-22 22:20:355116 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425117 const HttpAlternateProtocols& alternate_protocols =
5118 session->alternate_protocols();
5119 EXPECT_FALSE(
5120 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5121
5122 EXPECT_EQ(OK, callback.WaitForResult());
5123
5124 const HttpResponseInfo* response = trans->GetResponseInfo();
5125 ASSERT_TRUE(response != NULL);
5126 ASSERT_TRUE(response->headers != NULL);
5127 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535128 EXPECT_FALSE(response->was_fetched_via_spdy);
5129 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575130 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425131
5132 std::string response_data;
5133 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5134 EXPECT_EQ("hello world", response_data);
5135
5136 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5137 const HttpAlternateProtocols::PortProtocolPair alternate =
5138 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5139 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5140 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355141 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425142 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425143
[email protected]31e2c69e2010-04-15 18:06:065144 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:425145 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:425146}
5147
5148TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:065149 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:425150 SessionDependencies session_deps;
5151
5152 HttpRequestInfo request;
5153 request.method = "GET";
5154 request.url = GURL("http://www.google.com/");
5155 request.load_flags = 0;
5156
5157 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5158 StaticSocketDataProvider first_data;
5159 first_data.set_connect_data(mock_connect);
5160 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5161
5162 MockRead data_reads[] = {
5163 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5164 MockRead("hello world"),
5165 MockRead(true, OK),
5166 };
5167 StaticSocketDataProvider second_data(
5168 data_reads, arraysize(data_reads), NULL, 0);
5169 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5170
5171 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5172 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5173 // http://crbug.com/37454.
5174 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5175
5176 TestCompletionCallback callback;
5177
5178 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5179
[email protected]2fbaecf22010-07-22 22:20:355180 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425181 HttpAlternateProtocols* alternate_protocols =
5182 session->mutable_alternate_protocols();
5183 alternate_protocols->SetAlternateProtocolFor(
5184 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355185 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425186
5187 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5188
[email protected]5a1d7ca2010-04-28 20:12:275189 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425190 EXPECT_EQ(ERR_IO_PENDING, rv);
5191 EXPECT_EQ(OK, callback.WaitForResult());
5192
5193 const HttpResponseInfo* response = trans->GetResponseInfo();
5194 ASSERT_TRUE(response != NULL);
5195 ASSERT_TRUE(response->headers != NULL);
5196 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5197
5198 std::string response_data;
5199 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5200 EXPECT_EQ("hello world", response_data);
5201
5202 ASSERT_TRUE(
5203 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5204 const HttpAlternateProtocols::PortProtocolPair alternate =
5205 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5206 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065207 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425208}
5209
5210// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5211// says that it does SPDY, but it just does the TLS handshake, but the NPN
5212// response does not indicate SPDY, so we just do standard HTTPS over the port.
5213// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5214// on the original port.
[email protected]a2cb8122010-03-10 17:22:425215// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5216// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535217//
[email protected]a2cb8122010-03-10 17:22:425218// HttpRequestInfo request;
5219// request.method = "GET";
5220// request.url = GURL("http://www.google.com/");
5221// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535222//
[email protected]a2cb8122010-03-10 17:22:425223// MockRead data_reads[] = {
5224// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5225// MockRead("hello world"),
5226// MockRead(true, OK),
5227// };
5228// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5229// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535230//
[email protected]a2cb8122010-03-10 17:22:425231// SSLSocketDataProvider ssl(true, OK);
5232// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535233//
[email protected]a2cb8122010-03-10 17:22:425234// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535235//
[email protected]a2cb8122010-03-10 17:22:425236// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535237//
[email protected]a2cb8122010-03-10 17:22:425238// HostPortPair http_host_port_pair;
5239// http_host_port_pair.host = "www.google.com";
5240// http_host_port_pair.port = 80;
5241// HttpAlternateProtocols* alternate_protocols =
5242// session->mutable_alternate_protocols();
5243// alternate_protocols->SetAlternateProtocolFor(
5244// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065245// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535246//
[email protected]a2cb8122010-03-10 17:22:425247// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535248//
[email protected]5a1d7ca2010-04-28 20:12:275249// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425250// EXPECT_EQ(ERR_IO_PENDING, rv);
5251// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535252//
[email protected]a2cb8122010-03-10 17:22:425253// const HttpResponseInfo* response = trans->GetResponseInfo();
5254// ASSERT_TRUE(response != NULL);
5255// ASSERT_TRUE(response->headers != NULL);
5256// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535257//
[email protected]a2cb8122010-03-10 17:22:425258// std::string response_data;
5259// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5260// EXPECT_EQ("hello world", response_data);
5261// }
5262
5263TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065264 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355265 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425266 SessionDependencies session_deps;
5267
5268 HttpRequestInfo request;
5269 request.method = "GET";
5270 request.url = GURL("http://www.google.com/");
5271 request.load_flags = 0;
5272
[email protected]a2cb8122010-03-10 17:22:425273 StaticSocketDataProvider first_tcp_connect;
5274 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5275
5276 SSLSocketDataProvider ssl(true, OK);
5277 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5278
[email protected]564b4912010-03-09 16:30:425279 MockRead data_reads[] = {
5280 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5281 MockRead("hello world"),
5282 MockRead(true, OK),
5283 };
[email protected]a2cb8122010-03-10 17:22:425284 StaticSocketDataProvider fallback_data(
5285 data_reads, arraysize(data_reads), NULL, 0);
5286 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425287
5288 TestCompletionCallback callback;
5289
5290 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5291
[email protected]2fbaecf22010-07-22 22:20:355292 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425293 HttpAlternateProtocols* alternate_protocols =
5294 session->mutable_alternate_protocols();
5295 alternate_protocols->SetAlternateProtocolFor(
5296 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355297 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425298
5299 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5300
[email protected]5a1d7ca2010-04-28 20:12:275301 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425302 EXPECT_EQ(ERR_IO_PENDING, rv);
5303 EXPECT_EQ(OK, callback.WaitForResult());
5304
5305 const HttpResponseInfo* response = trans->GetResponseInfo();
5306 ASSERT_TRUE(response != NULL);
5307 ASSERT_TRUE(response->headers != NULL);
5308 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5309
5310 std::string response_data;
5311 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5312 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545313 HttpNetworkTransaction::SetNextProtos("");
5314 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5315}
5316
5317TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5318 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355319 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545320 SessionDependencies session_deps;
5321
5322 HttpRequestInfo request;
5323 request.method = "GET";
5324 request.url = GURL("http://www.google.com/");
5325 request.load_flags = 0;
5326
5327 MockRead data_reads[] = {
5328 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355329 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545330 MockRead("hello world"),
5331 MockRead(true, OK),
5332 };
5333
5334 StaticSocketDataProvider first_transaction(
5335 data_reads, arraysize(data_reads), NULL, 0);
5336 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5337
5338 SSLSocketDataProvider ssl(true, OK);
5339 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355340 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535341 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545342 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5343
[email protected]2bd93022010-07-17 00:58:445344 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135345 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545346
[email protected]2bd93022010-07-17 00:58:445347 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5348 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545349 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135350 CreateMockRead(*resp),
5351 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545352 MockRead(true, 0, 0),
5353 };
5354
5355 scoped_refptr<DelayedSocketData> spdy_data(
5356 new DelayedSocketData(
5357 1, // wait for one write to finish before reading.
5358 spdy_reads, arraysize(spdy_reads),
5359 spdy_writes, arraysize(spdy_writes)));
5360 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5361
5362 TestCompletionCallback callback;
5363
5364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5365 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5366
[email protected]5a1d7ca2010-04-28 20:12:275367 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545368 EXPECT_EQ(ERR_IO_PENDING, rv);
5369 EXPECT_EQ(OK, callback.WaitForResult());
5370
5371 const HttpResponseInfo* response = trans->GetResponseInfo();
5372 ASSERT_TRUE(response != NULL);
5373 ASSERT_TRUE(response->headers != NULL);
5374 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5375
5376 std::string response_data;
5377 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5378 EXPECT_EQ("hello world", response_data);
5379
5380 trans.reset(new HttpNetworkTransaction(session));
5381
[email protected]5a1d7ca2010-04-28 20:12:275382 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545383 EXPECT_EQ(ERR_IO_PENDING, rv);
5384 EXPECT_EQ(OK, callback.WaitForResult());
5385
5386 response = trans->GetResponseInfo();
5387 ASSERT_TRUE(response != NULL);
5388 ASSERT_TRUE(response->headers != NULL);
5389 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535390 EXPECT_TRUE(response->was_fetched_via_spdy);
5391 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575392 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545393
5394 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5395 EXPECT_EQ("hello!", response_data);
5396
5397 HttpNetworkTransaction::SetNextProtos("");
5398 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5399}
5400
[email protected]631f1322010-04-30 17:59:115401class CapturingProxyResolver : public ProxyResolver {
5402 public:
5403 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5404 virtual ~CapturingProxyResolver() {}
5405
5406 virtual int GetProxyForURL(const GURL& url,
5407 ProxyInfo* results,
5408 CompletionCallback* callback,
5409 RequestHandle* request,
5410 const BoundNetLog& net_log) {
[email protected]d911f1b2010-05-05 22:39:425411 ProxyServer proxy_server(
5412 ProxyServer::SCHEME_HTTP, "myproxy", 80);
5413 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115414 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425415 return OK;
[email protected]631f1322010-04-30 17:59:115416 }
5417
5418 virtual void CancelRequest(RequestHandle request) {
5419 NOTREACHED();
5420 }
5421
[email protected]24476402010-07-20 20:55:175422 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:115423 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425424 return OK;
[email protected]631f1322010-04-30 17:59:115425 }
5426
[email protected]24476402010-07-20 20:55:175427 const std::vector<GURL>& resolved() const { return resolved_; }
5428
5429 private:
[email protected]631f1322010-04-30 17:59:115430 std::vector<GURL> resolved_;
5431
5432 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5433};
5434
[email protected]631f1322010-04-30 17:59:115435TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5436 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355437 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:115438
5439 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425440 proxy_config.set_auto_detect(true);
5441 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115442
[email protected]631f1322010-04-30 17:59:115443 CapturingProxyResolver* capturing_proxy_resolver =
5444 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385445 SessionDependencies session_deps(new ProxyService(
5446 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5447 NULL));
[email protected]631f1322010-04-30 17:59:115448
5449 HttpRequestInfo request;
5450 request.method = "GET";
5451 request.url = GURL("http://www.google.com/");
5452 request.load_flags = 0;
5453
5454 MockRead data_reads[] = {
5455 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355456 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:115457 MockRead("hello world"),
5458 MockRead(true, OK),
5459 };
5460
5461 StaticSocketDataProvider first_transaction(
5462 data_reads, arraysize(data_reads), NULL, 0);
5463 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5464
5465 SSLSocketDataProvider ssl(true, OK);
5466 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355467 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535468 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115469 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5470
[email protected]2bd93022010-07-17 00:58:445471 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:115472 MockWrite spdy_writes[] = {
5473 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5474 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425475 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135476 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115477 };
5478
[email protected]d911f1b2010-05-05 22:39:425479 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5480
[email protected]2bd93022010-07-17 00:58:445481 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5482 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:115483 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425484 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135485 CreateMockRead(*resp.get(), 4), // 2, 4
5486 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425487 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115488 };
5489
[email protected]d911f1b2010-05-05 22:39:425490 scoped_refptr<OrderedSocketData> spdy_data(
5491 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115492 spdy_reads, arraysize(spdy_reads),
5493 spdy_writes, arraysize(spdy_writes)));
5494 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5495
5496 TestCompletionCallback callback;
5497
5498 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5499 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5500
5501 int rv = trans->Start(&request, &callback, BoundNetLog());
5502 EXPECT_EQ(ERR_IO_PENDING, rv);
5503 EXPECT_EQ(OK, callback.WaitForResult());
5504
5505 const HttpResponseInfo* response = trans->GetResponseInfo();
5506 ASSERT_TRUE(response != NULL);
5507 ASSERT_TRUE(response->headers != NULL);
5508 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535509 EXPECT_FALSE(response->was_fetched_via_spdy);
5510 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115511
5512 std::string response_data;
5513 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5514 EXPECT_EQ("hello world", response_data);
5515
5516 trans.reset(new HttpNetworkTransaction(session));
5517
5518 rv = trans->Start(&request, &callback, BoundNetLog());
5519 EXPECT_EQ(ERR_IO_PENDING, rv);
5520 EXPECT_EQ(OK, callback.WaitForResult());
5521
5522 response = trans->GetResponseInfo();
5523 ASSERT_TRUE(response != NULL);
5524 ASSERT_TRUE(response->headers != NULL);
5525 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535526 EXPECT_TRUE(response->was_fetched_via_spdy);
5527 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115528
5529 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5530 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425531 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5532 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115533 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425534 EXPECT_EQ("https://www.google.com/",
5535 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115536
5537 HttpNetworkTransaction::SetNextProtos("");
5538 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5539}
[email protected]631f1322010-04-30 17:59:115540
[email protected]2ff8b312010-04-26 22:20:545541TEST_F(HttpNetworkTransactionTest,
5542 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5543 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355544 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545545 SessionDependencies session_deps;
5546
5547 HttpRequestInfo request;
5548 request.method = "GET";
5549 request.url = GURL("http://www.google.com/");
5550 request.load_flags = 0;
5551
5552 MockRead data_reads[] = {
5553 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355554 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545555 MockRead("hello world"),
5556 MockRead(true, OK),
5557 };
5558
5559 StaticSocketDataProvider first_transaction(
5560 data_reads, arraysize(data_reads), NULL, 0);
5561 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5562
5563 SSLSocketDataProvider ssl(true, OK);
5564 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355565 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535566 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545567 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535568 // Make sure we use ssl for spdy here.
5569 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545570
[email protected]2bd93022010-07-17 00:58:445571 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135572 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545573
[email protected]2bd93022010-07-17 00:58:445574 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5575 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545576 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135577 CreateMockRead(*resp),
5578 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545579 MockRead(true, 0, 0),
5580 };
5581
5582 scoped_refptr<DelayedSocketData> spdy_data(
5583 new DelayedSocketData(
5584 1, // wait for one write to finish before reading.
5585 spdy_reads, arraysize(spdy_reads),
5586 spdy_writes, arraysize(spdy_writes)));
5587 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5588
5589 TestCompletionCallback callback;
5590
5591 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5592
5593 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5594
[email protected]5a1d7ca2010-04-28 20:12:275595 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545596 EXPECT_EQ(ERR_IO_PENDING, rv);
5597 EXPECT_EQ(OK, callback.WaitForResult());
5598
5599 const HttpResponseInfo* response = trans->GetResponseInfo();
5600 ASSERT_TRUE(response != NULL);
5601 ASSERT_TRUE(response->headers != NULL);
5602 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5603
5604 std::string response_data;
5605 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5606 EXPECT_EQ("hello world", response_data);
5607
5608 // Set up an initial SpdySession in the pool to reuse.
[email protected]b261d0e2010-08-02 19:13:245609 HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT");
[email protected]2ff8b312010-04-26 22:20:545610 scoped_refptr<SpdySession> spdy_session =
[email protected]b261d0e2010-08-02 19:13:245611 session->spdy_session_pool()->Get(pair, session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215612 scoped_refptr<TCPSocketParams> tcp_params =
5613 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365614 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545615 trans.reset(new HttpNetworkTransaction(session));
5616
[email protected]5a1d7ca2010-04-28 20:12:275617 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545618 EXPECT_EQ(ERR_IO_PENDING, rv);
5619 EXPECT_EQ(OK, callback.WaitForResult());
5620
5621 response = trans->GetResponseInfo();
5622 ASSERT_TRUE(response != NULL);
5623 ASSERT_TRUE(response->headers != NULL);
5624 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535625 EXPECT_TRUE(response->was_fetched_via_spdy);
5626 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575627 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545628
5629 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5630 EXPECT_EQ("hello!", response_data);
5631
5632 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065633 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425634}
5635
[email protected]044de0642010-06-17 10:42:155636// GenerateAuthToken is a mighty big test.
5637// It tests all permutation of GenerateAuthToken behavior:
5638// - Synchronous and Asynchronous completion.
5639// - OK or error on completion.
5640// - Direct connection, non-authenticating proxy, and authenticating proxy.
5641// - HTTP or HTTPS backend (to include proxy tunneling).
5642// - Non-authenticating and authenticating backend.
5643//
5644// In all, there are 44 reasonable permuations (for example, if there are
5645// problems generating an auth token for an authenticating proxy, we don't
5646// need to test all permutations of the backend server).
5647//
5648// The test proceeds by going over each of the configuration cases, and
5649// potentially running up to three rounds in each of the tests. The TestConfig
5650// specifies both the configuration for the test as well as the expectations
5651// for the results.
5652TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5653 const char* kServer = "http://www.example.com";
5654 const char* kSecureServer = "https://www.example.com";
5655 const char* kProxy = "myproxy:70";
5656 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5657
5658 enum AuthTiming {
5659 AUTH_NONE,
5660 AUTH_SYNC,
5661 AUTH_ASYNC,
5662 };
5663
5664 const MockWrite kGet(
5665 "GET / HTTP/1.1\r\n"
5666 "Host: www.example.com\r\n"
5667 "Connection: keep-alive\r\n\r\n");
5668 const MockWrite kGetProxy(
5669 "GET http://www.example.com/ HTTP/1.1\r\n"
5670 "Host: www.example.com\r\n"
5671 "Proxy-Connection: keep-alive\r\n\r\n");
5672 const MockWrite kGetAuth(
5673 "GET / HTTP/1.1\r\n"
5674 "Host: www.example.com\r\n"
5675 "Connection: keep-alive\r\n"
5676 "Authorization: auth_token\r\n\r\n");
5677 const MockWrite kGetProxyAuth(
5678 "GET http://www.example.com/ HTTP/1.1\r\n"
5679 "Host: www.example.com\r\n"
5680 "Proxy-Connection: keep-alive\r\n"
5681 "Proxy-Authorization: auth_token\r\n\r\n");
5682 const MockWrite kGetAuthThroughProxy(
5683 "GET http://www.example.com/ HTTP/1.1\r\n"
5684 "Host: www.example.com\r\n"
5685 "Proxy-Connection: keep-alive\r\n"
5686 "Authorization: auth_token\r\n\r\n");
5687 const MockWrite kGetAuthWithProxyAuth(
5688 "GET http://www.example.com/ HTTP/1.1\r\n"
5689 "Host: www.example.com\r\n"
5690 "Proxy-Connection: keep-alive\r\n"
5691 "Proxy-Authorization: auth_token\r\n"
5692 "Authorization: auth_token\r\n\r\n");
5693 const MockWrite kConnect(
5694 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5695 "Host: www.example.com\r\n"
5696 "Proxy-Connection: keep-alive\r\n\r\n");
5697 const MockWrite kConnectProxyAuth(
5698 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5699 "Host: www.example.com\r\n"
5700 "Proxy-Connection: keep-alive\r\n"
5701 "Proxy-Authorization: auth_token\r\n\r\n");
5702
5703 const MockRead kSuccess(
5704 "HTTP/1.1 200 OK\r\n"
5705 "Content-Type: text/html; charset=iso-8859-1\r\n"
5706 "Content-Length: 3\r\n\r\n"
5707 "Yes");
5708 const MockRead kFailure(
5709 "Should not be called.");
5710 const MockRead kServerChallenge(
5711 "HTTP/1.1 401 Unauthorized\r\n"
5712 "WWW-Authenticate: Mock realm=server\r\n"
5713 "Content-Type: text/html; charset=iso-8859-1\r\n"
5714 "Content-Length: 14\r\n\r\n"
5715 "Unauthorized\r\n");
5716 const MockRead kProxyChallenge(
5717 "HTTP/1.1 407 Unauthorized\r\n"
5718 "Proxy-Authenticate: Mock realm=proxy\r\n"
5719 "Proxy-Connection: close\r\n"
5720 "Content-Type: text/html; charset=iso-8859-1\r\n"
5721 "Content-Length: 14\r\n\r\n"
5722 "Unauthorized\r\n");
5723 const MockRead kProxyConnected(
5724 "HTTP/1.1 200 Connection Established\r\n\r\n");
5725
5726 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5727 // no constructors, but the C++ compiler on Windows warns about
5728 // unspecified data in compound literals. So, moved to using constructors,
5729 // and TestRound's created with the default constructor should not be used.
5730 struct TestRound {
5731 TestRound()
5732 : expected_rv(ERR_UNEXPECTED),
5733 extra_write(NULL),
5734 extra_read(NULL) {
5735 }
5736 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5737 int expected_rv_arg)
5738 : write(write_arg),
5739 read(read_arg),
5740 expected_rv(expected_rv_arg),
5741 extra_write(NULL),
5742 extra_read(NULL) {
5743 }
5744 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5745 int expected_rv_arg, const MockWrite* extra_write_arg,
5746 const MockWrite* extra_read_arg)
5747 : write(write_arg),
5748 read(read_arg),
5749 expected_rv(expected_rv_arg),
5750 extra_write(extra_write_arg),
5751 extra_read(extra_read_arg) {
5752 }
5753 MockWrite write;
5754 MockRead read;
5755 int expected_rv;
5756 const MockWrite* extra_write;
5757 const MockRead* extra_read;
5758 };
5759
5760 static const int kNoSSL = 500;
5761
5762 struct TestConfig {
5763 const char* proxy_url;
5764 AuthTiming proxy_auth_timing;
5765 int proxy_auth_rv;
5766 const char* server_url;
5767 AuthTiming server_auth_timing;
5768 int server_auth_rv;
5769 int num_auth_rounds;
5770 int first_ssl_round;
5771 TestRound rounds[3];
5772 } test_configs[] = {
5773 // Non-authenticating HTTP server with a direct connection.
5774 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5775 { TestRound(kGet, kSuccess, OK)}},
5776 // Authenticating HTTP server with a direct connection.
5777 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5778 { TestRound(kGet, kServerChallenge, OK),
5779 TestRound(kGetAuth, kSuccess, OK)}},
5780 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5781 { TestRound(kGet, kServerChallenge, OK),
5782 TestRound(kGetAuth, kFailure, kAuthErr)}},
5783 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5784 { TestRound(kGet, kServerChallenge, OK),
5785 TestRound(kGetAuth, kSuccess, OK)}},
5786 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5787 { TestRound(kGet, kServerChallenge, OK),
5788 TestRound(kGetAuth, kFailure, kAuthErr)}},
5789 // Non-authenticating HTTP server through a non-authenticating proxy.
5790 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5791 { TestRound(kGetProxy, kSuccess, OK)}},
5792 // Authenticating HTTP server through a non-authenticating proxy.
5793 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5794 { TestRound(kGetProxy, kServerChallenge, OK),
5795 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5796 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5797 { TestRound(kGetProxy, kServerChallenge, OK),
5798 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5799 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5800 { TestRound(kGetProxy, kServerChallenge, OK),
5801 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5802 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5803 { TestRound(kGetProxy, kServerChallenge, OK),
5804 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5805 // Non-authenticating HTTP server through an authenticating proxy.
5806 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5807 { TestRound(kGetProxy, kProxyChallenge, OK),
5808 TestRound(kGetProxyAuth, kSuccess, OK)}},
5809 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5810 { TestRound(kGetProxy, kProxyChallenge, OK),
5811 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5812 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5813 { TestRound(kGetProxy, kProxyChallenge, OK),
5814 TestRound(kGetProxyAuth, kSuccess, OK)}},
5815 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5816 { TestRound(kGetProxy, kProxyChallenge, OK),
5817 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5818 // Authenticating HTTP server through an authenticating proxy.
5819 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5820 { TestRound(kGetProxy, kProxyChallenge, OK),
5821 TestRound(kGetProxyAuth, kServerChallenge, OK),
5822 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5823 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5824 { TestRound(kGetProxy, kProxyChallenge, OK),
5825 TestRound(kGetProxyAuth, kServerChallenge, OK),
5826 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5827 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5828 { TestRound(kGetProxy, kProxyChallenge, OK),
5829 TestRound(kGetProxyAuth, kServerChallenge, OK),
5830 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5831 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5832 { TestRound(kGetProxy, kProxyChallenge, OK),
5833 TestRound(kGetProxyAuth, kServerChallenge, OK),
5834 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5835 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5836 { TestRound(kGetProxy, kProxyChallenge, OK),
5837 TestRound(kGetProxyAuth, kServerChallenge, OK),
5838 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5839 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5840 { TestRound(kGetProxy, kProxyChallenge, OK),
5841 TestRound(kGetProxyAuth, kServerChallenge, OK),
5842 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5843 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5844 { TestRound(kGetProxy, kProxyChallenge, OK),
5845 TestRound(kGetProxyAuth, kServerChallenge, OK),
5846 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5847 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5848 { TestRound(kGetProxy, kProxyChallenge, OK),
5849 TestRound(kGetProxyAuth, kServerChallenge, OK),
5850 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5851 // Non-authenticating HTTPS server with a direct connection.
5852 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5853 { TestRound(kGet, kSuccess, OK)}},
5854 // Authenticating HTTPS server with a direct connection.
5855 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5856 { TestRound(kGet, kServerChallenge, OK),
5857 TestRound(kGetAuth, kSuccess, OK)}},
5858 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5859 { TestRound(kGet, kServerChallenge, OK),
5860 TestRound(kGetAuth, kFailure, kAuthErr)}},
5861 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5862 { TestRound(kGet, kServerChallenge, OK),
5863 TestRound(kGetAuth, kSuccess, OK)}},
5864 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5865 { TestRound(kGet, kServerChallenge, OK),
5866 TestRound(kGetAuth, kFailure, kAuthErr)}},
5867 // Non-authenticating HTTPS server with a non-authenticating proxy.
5868 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5869 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5870 // Authenticating HTTPS server through a non-authenticating proxy.
5871 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5872 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5873 TestRound(kGetAuth, kSuccess, OK)}},
5874 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5875 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5876 TestRound(kGetAuth, kFailure, kAuthErr)}},
5877 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5878 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5879 TestRound(kGetAuth, kSuccess, OK)}},
5880 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5881 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5882 TestRound(kGetAuth, kFailure, kAuthErr)}},
5883 // Non-Authenticating HTTPS server through an authenticating proxy.
5884 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5885 { TestRound(kConnect, kProxyChallenge, OK),
5886 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5887 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5888 { TestRound(kConnect, kProxyChallenge, OK),
5889 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5890 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5891 { TestRound(kConnect, kProxyChallenge, OK),
5892 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5893 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5894 { TestRound(kConnect, kProxyChallenge, OK),
5895 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5896 // Authenticating HTTPS server through an authenticating proxy.
5897 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5898 { TestRound(kConnect, kProxyChallenge, OK),
5899 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5900 &kGet, &kServerChallenge),
5901 TestRound(kGetAuth, kSuccess, OK)}},
5902 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5903 { TestRound(kConnect, kProxyChallenge, OK),
5904 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5905 &kGet, &kServerChallenge),
5906 TestRound(kGetAuth, kFailure, kAuthErr)}},
5907 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5908 { TestRound(kConnect, kProxyChallenge, OK),
5909 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5910 &kGet, &kServerChallenge),
5911 TestRound(kGetAuth, kSuccess, OK)}},
5912 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5913 { TestRound(kConnect, kProxyChallenge, OK),
5914 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5915 &kGet, &kServerChallenge),
5916 TestRound(kGetAuth, kFailure, kAuthErr)}},
5917 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5918 { TestRound(kConnect, kProxyChallenge, OK),
5919 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5920 &kGet, &kServerChallenge),
5921 TestRound(kGetAuth, kSuccess, OK)}},
5922 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5923 { TestRound(kConnect, kProxyChallenge, OK),
5924 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5925 &kGet, &kServerChallenge),
5926 TestRound(kGetAuth, kFailure, kAuthErr)}},
5927 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5928 { TestRound(kConnect, kProxyChallenge, OK),
5929 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5930 &kGet, &kServerChallenge),
5931 TestRound(kGetAuth, kSuccess, OK)}},
5932 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5933 { TestRound(kConnect, kProxyChallenge, OK),
5934 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5935 &kGet, &kServerChallenge),
5936 TestRound(kGetAuth, kFailure, kAuthErr)}},
5937 };
5938
5939 SessionDependencies session_deps;
5940 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005941 HttpAuthHandlerMock::Factory* auth_factory(
5942 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155943 session_deps.http_auth_handler_factory.reset(auth_factory);
5944
5945 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5946 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:265947
5948 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:155949 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005950 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155951 std::string auth_challenge = "Mock realm=proxy";
5952 GURL origin(test_config.proxy_url);
5953 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5954 auth_challenge.end());
5955 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5956 origin, BoundNetLog());
5957 auth_handler->SetGenerateExpectation(
5958 test_config.proxy_auth_timing == AUTH_ASYNC,
5959 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:155960 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5961 }
5962 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005963 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155964 std::string auth_challenge = "Mock realm=server";
5965 GURL origin(test_config.server_url);
5966 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5967 auth_challenge.end());
5968 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5969 origin, BoundNetLog());
5970 auth_handler->SetGenerateExpectation(
5971 test_config.server_auth_timing == AUTH_ASYNC,
5972 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:155973 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5974 }
5975 if (test_config.proxy_url) {
5976 session_deps.proxy_service =
5977 CreateFixedProxyService(test_config.proxy_url);
5978 } else {
5979 session_deps.proxy_service = ProxyService::CreateNull();
5980 }
5981
5982 HttpRequestInfo request;
5983 request.method = "GET";
5984 request.url = GURL(test_config.server_url);
5985 request.load_flags = 0;
5986
5987 scoped_ptr<HttpTransaction> trans(
5988 new HttpNetworkTransaction(CreateSession(&session_deps)));
5989
5990 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5991 const TestRound& read_write_round = test_config.rounds[round];
5992
5993 // Set up expected reads and writes.
5994 MockRead reads[2];
5995 reads[0] = read_write_round.read;
5996 size_t length_reads = 1;
5997 if (read_write_round.extra_read) {
5998 reads[1] = *read_write_round.extra_read;
5999 length_reads = 2;
6000 }
6001
6002 MockWrite writes[2];
6003 writes[0] = read_write_round.write;
6004 size_t length_writes = 1;
6005 if (read_write_round.extra_write) {
6006 writes[1] = *read_write_round.extra_write;
6007 length_writes = 2;
6008 }
6009 StaticSocketDataProvider data_provider(
6010 reads, length_reads, writes, length_writes);
6011 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6012
6013 // Add an SSL sequence if necessary.
6014 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6015 if (round >= test_config.first_ssl_round)
6016 session_deps.socket_factory.AddSSLSocketDataProvider(
6017 &ssl_socket_data_provider);
6018
6019 // Start or restart the transaction.
6020 TestCompletionCallback callback;
6021 int rv;
6022 if (round == 0) {
6023 rv = trans->Start(&request, &callback, BoundNetLog());
6024 } else {
[email protected]13c8a092010-07-29 06:15:446025 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156026 }
6027 if (rv == ERR_IO_PENDING)
6028 rv = callback.WaitForResult();
6029
6030 // Compare results with expected data.
6031 EXPECT_EQ(read_write_round.expected_rv, rv);
6032 const HttpResponseInfo* response = trans->GetResponseInfo();
6033 if (read_write_round.expected_rv == OK) {
6034 EXPECT_FALSE(response == NULL);
6035 } else {
6036 EXPECT_TRUE(response == NULL);
6037 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6038 continue;
6039 }
6040 if (round + 1 < test_config.num_auth_rounds) {
6041 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6042 } else {
6043 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6044 }
6045 }
[email protected]e5ae96a2010-04-14 20:12:456046 }
[email protected]e60e47a2010-07-14 03:37:186047
6048 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
6049 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:456050}
6051
[email protected]c871bce92010-07-15 21:51:146052TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6053 // Do multi-round authentication and make sure it works correctly.
6054 SessionDependencies session_deps;
6055 HttpAuthHandlerMock::Factory* auth_factory(
6056 new HttpAuthHandlerMock::Factory());
6057 session_deps.http_auth_handler_factory.reset(auth_factory);
6058 session_deps.proxy_service = ProxyService::CreateNull();
6059 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6060 session_deps.host_resolver->set_synchronous_mode(true);
6061
6062 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6063 auth_handler->set_connection_based(true);
6064 std::string auth_challenge = "Mock realm=server";
6065 GURL origin("http://www.example.com");
6066 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6067 auth_challenge.end());
6068 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6069 origin, BoundNetLog());
6070 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6071
6072 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6073 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6074
6075 int rv = OK;
6076 const HttpResponseInfo* response = NULL;
6077 HttpRequestInfo request;
6078 request.method = "GET";
6079 request.url = origin;
6080 request.load_flags = 0;
6081 TestCompletionCallback callback;
6082
6083 const MockWrite kGet(
6084 "GET / HTTP/1.1\r\n"
6085 "Host: www.example.com\r\n"
6086 "Connection: keep-alive\r\n\r\n");
6087 const MockWrite kGetAuth(
6088 "GET / HTTP/1.1\r\n"
6089 "Host: www.example.com\r\n"
6090 "Connection: keep-alive\r\n"
6091 "Authorization: auth_token\r\n\r\n");
6092
6093 const MockRead kServerChallenge(
6094 "HTTP/1.1 401 Unauthorized\r\n"
6095 "WWW-Authenticate: Mock realm=server\r\n"
6096 "Content-Type: text/html; charset=iso-8859-1\r\n"
6097 "Content-Length: 14\r\n\r\n"
6098 "Unauthorized\r\n");
6099 const MockRead kSuccess(
6100 "HTTP/1.1 200 OK\r\n"
6101 "Content-Type: text/html; charset=iso-8859-1\r\n"
6102 "Content-Length: 3\r\n\r\n"
6103 "Yes");
6104
6105 MockWrite writes[] = {
6106 // First round
6107 kGet,
6108 // Second round
6109 kGetAuth,
6110 // Third round
6111 kGetAuth,
6112 };
6113 MockRead reads[] = {
6114 // First round
6115 kServerChallenge,
6116 // Second round
6117 kServerChallenge,
6118 // Third round
6119 kSuccess,
6120 };
6121 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6122 writes, arraysize(writes));
6123 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6124
6125 // First round
6126 auth_handler->SetGenerateExpectation(false, OK);
6127 rv = trans->Start(&request, &callback, BoundNetLog());
6128 if (rv == ERR_IO_PENDING)
6129 rv = callback.WaitForResult();
6130 EXPECT_EQ(OK, rv);
6131 response = trans->GetResponseInfo();
6132 ASSERT_FALSE(response == NULL);
6133 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6134
6135 // Second round
6136 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446137 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146138 if (rv == ERR_IO_PENDING)
6139 rv = callback.WaitForResult();
6140 EXPECT_EQ(OK, rv);
6141 response = trans->GetResponseInfo();
6142 ASSERT_FALSE(response == NULL);
6143 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6144
6145 // Third round
6146 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446147 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146148 if (rv == ERR_IO_PENDING)
6149 rv = callback.WaitForResult();
6150 EXPECT_EQ(OK, rv);
6151 response = trans->GetResponseInfo();
6152 ASSERT_FALSE(response == NULL);
6153 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6154}
6155
[email protected]aeaca1f2010-04-20 22:05:216156class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6157 public:
[email protected]06650c52010-06-03 00:49:176158 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216159 : fail_all_(fail_all) {
6160 }
6161
6162 virtual MockRead GetNextRead() {
6163 if (fail_all_)
6164 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6165
6166 return MockRead(false /* async */,
6167 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6168 }
6169
6170 virtual MockWriteResult OnWrite(const std::string& data) {
6171 return MockWriteResult(false /* async */, data.size());
6172 }
6173
6174 void Reset() {
6175 }
6176
6177 private:
6178 const bool fail_all_;
6179};
6180
6181// Test that we restart a connection when we see a decompression failure from
6182// the peer during the handshake. (In the real world we'll restart with SSLv3
6183// and we won't offer DEFLATE in that case.)
6184TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6185 HttpRequestInfo request;
6186 request.method = "GET";
6187 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6188 request.load_flags = 0;
6189
6190 SessionDependencies session_deps;
6191 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6192 false /* fail all reads */);
6193 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6194 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116195 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216196 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6197 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6198 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6199 session_deps.socket_factory.AddSSLSocketDataProvider(
6200 &ssl_socket_data_provider1);
6201 session_deps.socket_factory.AddSSLSocketDataProvider(
6202 &ssl_socket_data_provider2);
6203
[email protected]e60e47a2010-07-14 03:37:186204 // Work around http://crbug.com/37454
6205 StaticSocketDataProvider bug37454_connection;
6206 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6207 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6208
[email protected]aeaca1f2010-04-20 22:05:216209 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6210 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6211 TestCompletionCallback callback;
6212
[email protected]5a1d7ca2010-04-28 20:12:276213 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216214 EXPECT_EQ(ERR_IO_PENDING, rv);
6215 EXPECT_EQ(OK, callback.WaitForResult());
6216
6217 const HttpResponseInfo* response = trans->GetResponseInfo();
6218 ASSERT_TRUE(response != NULL);
6219 ASSERT_TRUE(response->headers != NULL);
6220 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6221
6222 std::string response_data;
6223 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6224 EXPECT_EQ("ok.", response_data);
6225}
6226
6227// Test that we restart a connection if we get a decompression failure from the
6228// peer while reading the first bytes from the connection. This occurs when the
6229// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6230// in the handshake.
6231TEST_F(HttpNetworkTransactionTest,
6232 RestartAfterTLSDecompressionFailureWithFalseStart) {
6233 HttpRequestInfo request;
6234 request.method = "GET";
6235 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6236 request.load_flags = 0;
6237
6238 SessionDependencies session_deps;
6239 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6240 true /* fail all reads */);
6241 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6242 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6243 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6244 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6245 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6246 session_deps.socket_factory.AddSSLSocketDataProvider(
6247 &ssl_socket_data_provider1);
6248 session_deps.socket_factory.AddSSLSocketDataProvider(
6249 &ssl_socket_data_provider2);
6250
6251 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6252 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6253 TestCompletionCallback callback;
6254
[email protected]5a1d7ca2010-04-28 20:12:276255 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216256 EXPECT_EQ(ERR_IO_PENDING, rv);
6257 EXPECT_EQ(OK, callback.WaitForResult());
6258
6259 const HttpResponseInfo* response = trans->GetResponseInfo();
6260 ASSERT_TRUE(response != NULL);
6261 ASSERT_TRUE(response->headers != NULL);
6262 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6263
6264 std::string response_data;
6265 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6266 EXPECT_EQ("ok.", response_data);
6267}
6268
[email protected]65041fa2010-05-21 06:56:536269// This tests the case that a request is issued via http instead of spdy after
6270// npn is negotiated.
6271TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6272 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6273 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6274 SessionDependencies session_deps;
6275 HttpRequestInfo request;
6276 request.method = "GET";
6277 request.url = GURL("https://www.google.com/");
6278 request.load_flags = 0;
6279
6280 MockWrite data_writes[] = {
6281 MockWrite("GET / HTTP/1.1\r\n"
6282 "Host: www.google.com\r\n"
6283 "Connection: keep-alive\r\n\r\n"),
6284 };
6285
6286 MockRead data_reads[] = {
6287 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356288 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536289 MockRead("hello world"),
6290 MockRead(false, OK),
6291 };
6292
6293 SSLSocketDataProvider ssl(true, OK);
6294 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6295 ssl.next_proto = "http/1.1";
6296
6297 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6298
6299 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6300 data_writes, arraysize(data_writes));
6301 session_deps.socket_factory.AddSocketDataProvider(&data);
6302
6303 TestCompletionCallback callback;
6304
6305 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6306 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6307
6308 int rv = trans->Start(&request, &callback, BoundNetLog());
6309
6310 EXPECT_EQ(ERR_IO_PENDING, rv);
6311 EXPECT_EQ(OK, callback.WaitForResult());
6312
6313 const HttpResponseInfo* response = trans->GetResponseInfo();
6314 ASSERT_TRUE(response != NULL);
6315 ASSERT_TRUE(response->headers != NULL);
6316 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6317
6318 std::string response_data;
6319 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6320 EXPECT_EQ("hello world", response_data);
6321
6322 EXPECT_FALSE(response->was_fetched_via_spdy);
6323 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576324 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536325
6326 HttpNetworkTransaction::SetNextProtos("");
6327 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6328}
[email protected]26ef6582010-06-24 02:30:476329
6330TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6331 // Simulate the SSL handshake completing with an NPN negotiation
6332 // followed by an immediate server closing of the socket.
6333 // Fix crash: http://crbug.com/46369
6334 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:356335 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476336 SessionDependencies session_deps;
6337
6338 HttpRequestInfo request;
6339 request.method = "GET";
6340 request.url = GURL("https://www.google.com/");
6341 request.load_flags = 0;
6342
6343 SSLSocketDataProvider ssl(true, OK);
6344 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356345 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476346 ssl.was_npn_negotiated = true;
6347 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6348
[email protected]2bd93022010-07-17 00:58:446349 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136350 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476351
6352 MockRead spdy_reads[] = {
6353 MockRead(false, 0, 0) // Not async - return 0 immediately.
6354 };
6355
6356 scoped_refptr<DelayedSocketData> spdy_data(
6357 new DelayedSocketData(
6358 0, // don't wait in this case, immediate hangup.
6359 spdy_reads, arraysize(spdy_reads),
6360 spdy_writes, arraysize(spdy_writes)));
6361 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6362
6363 TestCompletionCallback callback;
6364
6365 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6366 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6367
6368 int rv = trans->Start(&request, &callback, BoundNetLog());
6369 EXPECT_EQ(ERR_IO_PENDING, rv);
6370 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6371
6372 HttpNetworkTransaction::SetNextProtos("");
6373 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6374}
[email protected]65d34382010-07-01 18:12:266375
[email protected]6cc42182010-08-02 11:27:026376TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
6377 // This test ensures that the URL passed into the proxy is upgraded
6378 // to https when doing an Alternate Protocol upgrade.
6379 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6380 HttpNetworkTransaction::SetNextProtos(
6381 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
6382
6383 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6384 HttpAuthHandlerMock::Factory* auth_factory =
6385 new HttpAuthHandlerMock::Factory();
6386 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
6387 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6388 auth_factory->set_do_init_from_challenge(true);
6389 session_deps.http_auth_handler_factory.reset(auth_factory);
6390
6391 HttpRequestInfo request;
6392 request.method = "GET";
6393 request.url = GURL("http://www.google.com");
6394 request.load_flags = 0;
6395
6396 // First round goes unauthenticated through the proxy.
6397 MockWrite data_writes_1[] = {
6398 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6399 "Host: www.google.com\r\n"
6400 "Proxy-Connection: keep-alive\r\n"
6401 "\r\n"),
6402 };
6403 MockRead data_reads_1[] = {
6404 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
6405 MockRead("HTTP/1.1 200 OK\r\n"
6406 "Alternate-Protocol: 443:npn-spdy/2\r\n"
6407 "Proxy-Connection: close\r\n"
6408 "\r\n"),
6409 };
6410 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
6411 data_writes_1, arraysize(data_writes_1));
6412
6413 // Second round tries to tunnel to www.google.com due to the
6414 // Alternate-Protocol announcement in the first round. It fails due
6415 // to a proxy authentication challenge.
6416 // After the failure, a tunnel is established to www.google.com using
6417 // Proxy-Authorization headers. There is then a SPDY request round.
6418 //
6419 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
6420 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
6421 // does a Disconnect and Connect on the same socket, rather than trying
6422 // to obtain a new one.
6423 //
6424 // NOTE: Originally, the proxy response to the second CONNECT request
6425 // simply returned another 407 so the unit test could skip the SSL connection
6426 // establishment and SPDY framing issues. Alas, the
6427 // retry-http-when-alternate-protocol fails logic kicks in, which was more
6428 // complicated to set up expectations for than the SPDY session.
6429
6430 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6431 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6432 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6433
6434 MockWrite data_writes_2[] = {
6435 // First connection attempt without Proxy-Authorization.
6436 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6437 "Host: www.google.com\r\n"
6438 "Proxy-Connection: keep-alive\r\n"
6439 "\r\n"),
6440
6441 // Second connection attempt with Proxy-Authorization.
6442 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6443 "Host: www.google.com\r\n"
6444 "Proxy-Connection: keep-alive\r\n"
6445 "Proxy-Authorization: auth_token\r\n"
6446 "\r\n"),
6447
6448 // SPDY request
6449 CreateMockWrite(*req),
6450 };
6451 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
6452 "Proxy-Authenticate: Mock\r\n"
6453 "Proxy-Connection: close\r\n"
6454 "\r\n");
6455 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6456 MockRead data_reads_2[] = {
6457 // First connection attempt fails
6458 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
6459 MockRead(true, kRejectConnectResponse,
6460 arraysize(kRejectConnectResponse) - 1, 1),
6461
6462 // Second connection attempt passes
6463 MockRead(true, kAcceptConnectResponse,
6464 arraysize(kAcceptConnectResponse) -1, 4),
6465
6466 // SPDY response
6467 CreateMockRead(*resp.get(), 6),
6468 CreateMockRead(*data.get(), 6),
6469 MockRead(true, 0, 0, 6),
6470 };
6471 scoped_refptr<OrderedSocketData> data_2(
6472 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
6473 data_writes_2, arraysize(data_writes_2)));
6474
6475 SSLSocketDataProvider ssl(true, OK);
6476 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6477 ssl.next_proto = "spdy/2";
6478 ssl.was_npn_negotiated = true;
6479
6480 session_deps.socket_factory.AddSocketDataProvider(&data_1);
6481 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
6482 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6483 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6484
6485 // First round should work and provide the Alternate-Protocol state.
6486 TestCompletionCallback callback_1;
6487 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
6488 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
6489 EXPECT_EQ(ERR_IO_PENDING, rv);
6490 EXPECT_EQ(OK, callback_1.WaitForResult());
6491
6492 // Second round should attempt a tunnel connect and get an auth challenge.
6493 TestCompletionCallback callback_2;
6494 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
6495 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
6496 EXPECT_EQ(ERR_IO_PENDING, rv);
6497 EXPECT_EQ(OK, callback_2.WaitForResult());
6498 const HttpResponseInfo* response = trans_2->GetResponseInfo();
6499 ASSERT_FALSE(response == NULL);
6500 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6501
6502 // Restart with auth. Tunnel should work and response received.
6503 TestCompletionCallback callback_3;
6504 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
6505 EXPECT_EQ(ERR_IO_PENDING, rv);
6506 EXPECT_EQ(OK, callback_3.WaitForResult());
6507
6508 // After all that work, these two lines (or actually, just the scheme) are
6509 // what this test is all about. Make sure it happens correctly.
6510 const GURL& request_url = auth_handler->request_url();
6511 EXPECT_EQ("https", request_url.scheme());
6512 EXPECT_EQ("www.google.com", request_url.host());
6513
6514 HttpNetworkTransaction::SetNextProtos("");
6515 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6516}
6517
[email protected]89ceba9a2009-03-21 03:46:066518} // namespace net