blob: 56b73c529285f42809e46c6f0537d5e8e99fcdee [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]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4223#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3324#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/test_completion_callback.h"
26#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1227#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0028#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2929#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5732#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3833#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5234#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5335#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1136#include "net/proxy/proxy_resolver.h"
37#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4438#include "net/socket/client_socket_factory.h"
39#include "net/socket/socket_test_util.h"
40#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5441#include "net/spdy/spdy_framer.h"
42#include "net/spdy/spdy_session.h"
43#include "net/spdy/spdy_session_pool.h"
44#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5245#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1546#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5247
48//-----------------------------------------------------------------------------
49
[email protected]13c8a092010-07-29 06:15:4450namespace {
51
52const string16 kBar(ASCIIToUTF16("bar"));
53const string16 kBar2(ASCIIToUTF16("bar2"));
54const string16 kBar3(ASCIIToUTF16("bar3"));
55const string16 kBaz(ASCIIToUTF16("baz"));
56const string16 kFirst(ASCIIToUTF16("first"));
57const string16 kFoo(ASCIIToUTF16("foo"));
58const string16 kFoo2(ASCIIToUTF16("foo2"));
59const string16 kFoo3(ASCIIToUTF16("foo3"));
60const string16 kFou(ASCIIToUTF16("fou"));
61const string16 kSecond(ASCIIToUTF16("second"));
62const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
63const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
64
65} // namespace
66
[email protected]89ceba9a2009-03-21 03:46:0667namespace net {
68
[email protected]2d731a32010-04-29 01:04:0669class HttpNetworkSessionPeer {
70 public:
71 explicit HttpNetworkSessionPeer(
72 const scoped_refptr<HttpNetworkSession>& session)
73 : session_(session) {}
74
75 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
76 session_->tcp_socket_pool_ = pool;
77 }
78
79 void SetSocketPoolForSOCKSProxy(
80 const HostPortPair& socks_proxy,
81 const scoped_refptr<SOCKSClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1882 session_->socks_socket_pools_[socks_proxy] = pool;
[email protected]2d731a32010-04-29 01:04:0683 }
84
85 void SetSocketPoolForHTTPProxy(
86 const HostPortPair& http_proxy,
[email protected]e772db3f2010-07-12 18:11:1387 const scoped_refptr<HttpProxyClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1888 session_->http_proxy_socket_pools_[http_proxy] = pool;
89 }
90
91 void SetSSLSocketPool(const scoped_refptr<SSLClientSocketPool>& pool) {
92 session_->ssl_socket_pool_ = pool;
93 }
94
95 void SetSocketPoolForSSLWithProxy(
96 const HostPortPair& proxy_host,
97 const scoped_refptr<SSLClientSocketPool>& pool) {
98 session_->ssl_socket_pools_for_proxies_[proxy_host] = pool;
[email protected]2d731a32010-04-29 01:04:0699 }
100
101 private:
102 const scoped_refptr<HttpNetworkSession> session_;
103
104 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
105};
106
[email protected]e44de5d2009-06-05 20:12:45107// Helper to manage the lifetimes of the dependencies for a
108// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44109struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59110 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42111 SessionDependencies()
112 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:37113 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:10114 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52115 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54116 spdy_session_pool(new SpdySessionPool()),
117 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59118
119 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45120 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42121 : host_resolver(new MockHostResolver),
122 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10123 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52124 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54125 spdy_session_pool(new SpdySessionPool()),
126 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59127
[email protected]a2c2fb92009-07-18 07:31:04128 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:09129 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42130 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59131 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50132 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52133 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]a7ea8832010-07-12 17:54:54134 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59135};
136
[email protected]1c773ea12009-04-28 19:58:42137ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50138 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48139 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39140 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53141}
142
[email protected]228ff742009-06-05 01:19:59143HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38144 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09145 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42146 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10147 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52148 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17149 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44150 NULL,
[email protected]a7ea8832010-07-12 17:54:54151 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14152}
153
[email protected]89836e22008-09-25 20:33:42154class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52155 public:
[email protected]2ff8b312010-04-26 22:20:54156 virtual void SetUp() {
157 spdy::SpdyFramer::set_enable_compression_default(false);
158 }
159
[email protected]0e75a732008-10-16 20:36:09160 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54161 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09162 // Empty the current queue.
163 MessageLoop::current()->RunAllPending();
164 PlatformTest::TearDown();
165 }
166
[email protected]3d2a59b2008-09-26 19:44:25167 protected:
168 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52169
[email protected]ff007e162009-05-23 09:13:15170 struct SimpleGetHelperResult {
171 int rv;
172 std::string status_line;
173 std::string response_data;
174 };
initial.commit586acc5fe2008-07-26 22:42:52175
[email protected]31a2bfe2010-02-09 08:03:39176 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
177 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15178 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52179
[email protected]228ff742009-06-05 01:19:59180 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40181 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43182 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52183
[email protected]ff007e162009-05-23 09:13:15184 HttpRequestInfo request;
185 request.method = "GET";
186 request.url = GURL("http://www.google.com/");
187 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52188
[email protected]31a2bfe2010-02-09 08:03:39189 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59190 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52191
[email protected]ff007e162009-05-23 09:13:15192 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52193
[email protected]169d0012010-05-10 23:20:12194 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
195 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15196 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52197
[email protected]ff007e162009-05-23 09:13:15198 out.rv = callback.WaitForResult();
199 if (out.rv != OK)
200 return out;
201
202 const HttpResponseInfo* response = trans->GetResponseInfo();
203 EXPECT_TRUE(response != NULL);
204
205 EXPECT_TRUE(response->headers != NULL);
206 out.status_line = response->headers->GetStatusLine();
207
208 rv = ReadTransaction(trans.get(), &out.response_data);
209 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39210 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12211 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
212 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39213 ExpectLogContainsSomewhere(
214 log.entries(), pos,
215 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
216 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15217
[email protected]aecfbf22008-10-16 02:02:47218 return out;
[email protected]ff007e162009-05-23 09:13:15219 }
initial.commit586acc5fe2008-07-26 22:42:52220
[email protected]ff007e162009-05-23 09:13:15221 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
222 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52223
[email protected]ff007e162009-05-23 09:13:15224 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15225};
[email protected]231d5a32008-09-13 00:45:27226
[email protected]15a5ccf82008-10-23 19:57:43227// Fill |str| with a long header list that consumes >= |size| bytes.
228void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19229 const char* row =
230 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
231 const int sizeof_row = strlen(row);
232 const int num_rows = static_cast<int>(
233 ceil(static_cast<float>(size) / sizeof_row));
234 const int sizeof_data = num_rows * sizeof_row;
235 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43236 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51237
[email protected]4ddaf2502008-10-23 18:26:19238 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43239 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19240}
241
[email protected]385a4672009-03-11 22:21:29242// Alternative functions that eliminate randomness and dependency on the local
243// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20244void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29245 static const uint8 bytes[] = {
246 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
247 };
248 static size_t current_byte = 0;
249 for (size_t i = 0; i < n; ++i) {
250 output[i] = bytes[current_byte++];
251 current_byte %= arraysize(bytes);
252 }
253}
254
[email protected]fe2bc6a2009-03-23 16:52:20255void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29256 static const uint8 bytes[] = {
257 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
258 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
259 };
260 static size_t current_byte = 0;
261 for (size_t i = 0; i < n; ++i) {
262 output[i] = bytes[current_byte++];
263 current_byte %= arraysize(bytes);
264 }
265}
266
[email protected]fe2bc6a2009-03-23 16:52:20267std::string MockGetHostName() {
268 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29269}
270
[email protected]e60e47a2010-07-14 03:37:18271template<typename ParentPool>
272class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31273 public:
[email protected]e60e47a2010-07-14 03:37:18274 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
275
[email protected]d80a4322009-08-14 07:07:49276 const std::string last_group_name_received() const {
277 return last_group_name_;
278 }
279
[email protected]684970b2009-08-14 04:54:46280 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49281 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31282 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31283 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46284 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53285 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31286 last_group_name_ = group_name;
287 return ERR_IO_PENDING;
288 }
[email protected]04e5be32009-06-26 20:00:31289 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21290 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31291 virtual void ReleaseSocket(const std::string& group_name,
292 ClientSocket* socket) {}
293 virtual void CloseIdleSockets() {}
294 virtual HostResolver* GetHostResolver() const {
295 return NULL;
296 }
297 virtual int IdleSocketCount() const {
298 return 0;
299 }
300 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
301 return 0;
302 }
303 virtual LoadState GetLoadState(const std::string& group_name,
304 const ClientSocketHandle* handle) const {
305 return LOAD_STATE_IDLE;
306 }
[email protected]a796bcec2010-03-22 17:17:26307 virtual base::TimeDelta ConnectionTimeout() const {
308 return base::TimeDelta();
309 }
[email protected]d80a4322009-08-14 07:07:49310
311 private:
[email protected]04e5be32009-06-26 20:00:31312 std::string last_group_name_;
313};
314
[email protected]2d731a32010-04-29 01:04:06315typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11316CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13317typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
318CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06319typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11320CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18321typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
322CaptureGroupNameSSLSocketPool;
323
324template<typename ParentPool>
325CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
326 HttpNetworkSession* session)
327 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
328
329template<>
330CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
331 HttpNetworkSession* session)
332 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
333 NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11334
[email protected]231d5a32008-09-13 00:45:27335//-----------------------------------------------------------------------------
336
[email protected]dae22c52010-07-30 02:16:35337// This is the expected list of advertised protocols from the browser's NPN
338// list.
339static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
340
341// This is the expected return from a current server advertising SPDY.
342static const char kAlternateProtocolHttpHeader[] =
343 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
344
[email protected]231d5a32008-09-13 00:45:27345TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59346 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40347 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43348 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27349}
350
351TEST_F(HttpNetworkTransactionTest, SimpleGET) {
352 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35353 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
354 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42355 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27356 };
[email protected]31a2bfe2010-02-09 08:03:39357 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
358 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42359 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27360 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
361 EXPECT_EQ("hello world", out.response_data);
362}
363
364// Response with no status line.
365TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
366 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35367 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42368 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27369 };
[email protected]31a2bfe2010-02-09 08:03:39370 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
371 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42372 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27373 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
374 EXPECT_EQ("hello world", out.response_data);
375}
376
377// Allow up to 4 bytes of junk to precede status line.
378TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
379 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35380 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42381 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27382 };
[email protected]31a2bfe2010-02-09 08:03:39383 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
384 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42385 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27386 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
387 EXPECT_EQ("DATA", out.response_data);
388}
389
390// Allow up to 4 bytes of junk to precede status line.
391TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
392 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35393 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42394 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27395 };
[email protected]31a2bfe2010-02-09 08:03:39396 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
397 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42398 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27399 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
400 EXPECT_EQ("DATA", out.response_data);
401}
402
403// Beyond 4 bytes of slop and it should fail to find a status line.
404TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
405 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35406 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42407 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27408 };
[email protected]31a2bfe2010-02-09 08:03:39409 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
410 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42411 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25412 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
413 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27414}
415
416// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
417TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
418 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35419 MockRead("\n"),
420 MockRead("\n"),
421 MockRead("Q"),
422 MockRead("J"),
423 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42424 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27425 };
[email protected]31a2bfe2010-02-09 08:03:39426 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
427 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42428 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27429 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
430 EXPECT_EQ("DATA", out.response_data);
431}
432
433// Close the connection before enough bytes to have a status line.
434TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
435 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35436 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42437 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27438 };
[email protected]31a2bfe2010-02-09 08:03:39439 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
440 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42441 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27442 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
443 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52444}
445
[email protected]f9d44aa2008-09-23 23:57:17446// Simulate a 204 response, lacking a Content-Length header, sent over a
447// persistent connection. The response should still terminate since a 204
448// cannot have a response body.
449TEST_F(HttpNetworkTransactionTest, StopsReading204) {
450 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35451 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
452 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42453 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17454 };
[email protected]31a2bfe2010-02-09 08:03:39455 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
456 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42457 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17458 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
459 EXPECT_EQ("", out.response_data);
460}
461
[email protected]0877e3d2009-10-17 22:29:57462// A simple request using chunked encoding with some extra data after.
463// (Like might be seen in a pipelined response.)
464TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
465 MockRead data_reads[] = {
466 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
467 MockRead("5\r\nHello\r\n"),
468 MockRead("1\r\n"),
469 MockRead(" \r\n"),
470 MockRead("5\r\nworld\r\n"),
471 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
472 MockRead(false, OK),
473 };
[email protected]31a2bfe2010-02-09 08:03:39474 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
475 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57476 EXPECT_EQ(OK, out.rv);
477 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
478 EXPECT_EQ("Hello world", out.response_data);
479}
480
[email protected]ef0faf2e72009-03-05 23:27:23481// Do a request using the HEAD method. Verify that we don't try to read the
482// message body (since HEAD has none).
483TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59484 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40485 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43486 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23487
[email protected]1c773ea12009-04-28 19:58:42488 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23489 request.method = "HEAD";
490 request.url = GURL("http://www.google.com/");
491 request.load_flags = 0;
492
493 MockWrite data_writes1[] = {
494 MockWrite("HEAD / HTTP/1.1\r\n"
495 "Host: www.google.com\r\n"
496 "Connection: keep-alive\r\n"
497 "Content-Length: 0\r\n\r\n"),
498 };
499 MockRead data_reads1[] = {
500 MockRead("HTTP/1.1 404 Not Found\r\n"),
501 MockRead("Server: Blah\r\n"),
502 MockRead("Content-Length: 1234\r\n\r\n"),
503
504 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42505 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23506 };
507
[email protected]31a2bfe2010-02-09 08:03:39508 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
509 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59510 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23511
512 TestCompletionCallback callback1;
513
[email protected]5a1d7ca2010-04-28 20:12:27514 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42515 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23516
517 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42518 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23519
[email protected]1c773ea12009-04-28 19:58:42520 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23521 EXPECT_FALSE(response == NULL);
522
523 // Check that the headers got parsed.
524 EXPECT_TRUE(response->headers != NULL);
525 EXPECT_EQ(1234, response->headers->GetContentLength());
526 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
527
528 std::string server_header;
529 void* iter = NULL;
530 bool has_server_header = response->headers->EnumerateHeader(
531 &iter, "Server", &server_header);
532 EXPECT_TRUE(has_server_header);
533 EXPECT_EQ("Blah", server_header);
534
535 // Reading should give EOF right away, since there is no message body
536 // (despite non-zero content-length).
537 std::string response_data;
538 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42539 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23540 EXPECT_EQ("", response_data);
541}
542
initial.commit586acc5fe2008-07-26 22:42:52543TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59544 SessionDependencies session_deps;
545 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52546
547 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35548 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
549 MockRead("hello"),
550 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
551 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42552 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52553 };
[email protected]31a2bfe2010-02-09 08:03:39554 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59555 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52556
557 const char* kExpectedResponseData[] = {
558 "hello", "world"
559 };
560
561 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43562 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52563
[email protected]1c773ea12009-04-28 19:58:42564 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52565 request.method = "GET";
566 request.url = GURL("http://www.google.com/");
567 request.load_flags = 0;
568
569 TestCompletionCallback callback;
570
[email protected]5a1d7ca2010-04-28 20:12:27571 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42572 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52573
574 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42575 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52576
[email protected]1c773ea12009-04-28 19:58:42577 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52578 EXPECT_TRUE(response != NULL);
579
580 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25581 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52582
583 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57584 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42585 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25586 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52587 }
588}
589
590TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59591 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40592 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43593 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52594
[email protected]1c773ea12009-04-28 19:58:42595 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52596 request.method = "POST";
597 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42598 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52599 request.upload_data->AppendBytes("foo", 3);
600 request.load_flags = 0;
601
602 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35603 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
604 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
605 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42606 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52607 };
[email protected]31a2bfe2010-02-09 08:03:39608 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59609 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52610
611 TestCompletionCallback callback;
612
[email protected]5a1d7ca2010-04-28 20:12:27613 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42614 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52615
616 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42617 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52618
[email protected]1c773ea12009-04-28 19:58:42619 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52620 EXPECT_TRUE(response != NULL);
621
622 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25623 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52624
625 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57626 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42627 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25628 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52629}
630
[email protected]3a2d3662009-03-27 03:49:14631// This test is almost the same as Ignores100 above, but the response contains
632// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57633// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14634TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59635 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40636 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43637 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14638
[email protected]1c773ea12009-04-28 19:58:42639 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14640 request.method = "GET";
641 request.url = GURL("http://www.foo.com/");
642 request.load_flags = 0;
643
644 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57645 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
646 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14647 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42648 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14649 };
[email protected]31a2bfe2010-02-09 08:03:39650 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59651 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14652
653 TestCompletionCallback callback;
654
[email protected]5a1d7ca2010-04-28 20:12:27655 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42656 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14657
658 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42659 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14660
[email protected]1c773ea12009-04-28 19:58:42661 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14662 EXPECT_TRUE(response != NULL);
663
664 EXPECT_TRUE(response->headers != NULL);
665 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
666
667 std::string response_data;
668 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42669 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14670 EXPECT_EQ("hello world", response_data);
671}
672
[email protected]ee9410e72010-01-07 01:42:38673TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
674 SessionDependencies session_deps;
675 scoped_ptr<HttpTransaction> trans(
676 new HttpNetworkTransaction(CreateSession(&session_deps)));
677
678 HttpRequestInfo request;
679 request.method = "POST";
680 request.url = GURL("http://www.foo.com/");
681 request.load_flags = 0;
682
683 MockRead data_reads[] = {
684 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
685 MockRead(true, 0),
686 };
[email protected]31a2bfe2010-02-09 08:03:39687 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38688 session_deps.socket_factory.AddSocketDataProvider(&data);
689
690 TestCompletionCallback callback;
691
[email protected]5a1d7ca2010-04-28 20:12:27692 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38693 EXPECT_EQ(ERR_IO_PENDING, rv);
694
695 rv = callback.WaitForResult();
696 EXPECT_EQ(OK, rv);
697
698 std::string response_data;
699 rv = ReadTransaction(trans.get(), &response_data);
700 EXPECT_EQ(OK, rv);
701 EXPECT_EQ("", response_data);
702}
703
704TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
705 SessionDependencies session_deps;
706 scoped_ptr<HttpTransaction> trans(
707 new HttpNetworkTransaction(CreateSession(&session_deps)));
708
709 HttpRequestInfo request;
710 request.method = "POST";
711 request.url = GURL("http://www.foo.com/");
712 request.load_flags = 0;
713
714 MockRead data_reads[] = {
715 MockRead(true, 0),
716 };
[email protected]31a2bfe2010-02-09 08:03:39717 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38718 session_deps.socket_factory.AddSocketDataProvider(&data);
719
720 TestCompletionCallback callback;
721
[email protected]5a1d7ca2010-04-28 20:12:27722 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38723 EXPECT_EQ(ERR_IO_PENDING, rv);
724
725 rv = callback.WaitForResult();
726 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
727}
728
[email protected]3d2a59b2008-09-26 19:44:25729// read_failure specifies a read failure that should cause the network
730// transaction to resend the request.
731void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
732 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59733 SessionDependencies session_deps;
734 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52735
[email protected]1c773ea12009-04-28 19:58:42736 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52737 request.method = "GET";
738 request.url = GURL("http://www.foo.com/");
739 request.load_flags = 0;
740
741 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35742 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
743 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25744 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52745 };
[email protected]31a2bfe2010-02-09 08:03:39746 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59747 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52748
749 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35750 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
751 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42752 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52753 };
[email protected]31a2bfe2010-02-09 08:03:39754 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59755 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52756
757 const char* kExpectedResponseData[] = {
758 "hello", "world"
759 };
760
761 for (int i = 0; i < 2; ++i) {
762 TestCompletionCallback callback;
763
[email protected]5695b8c2009-09-30 21:36:43764 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52765
[email protected]5a1d7ca2010-04-28 20:12:27766 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42767 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52768
769 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42770 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52771
[email protected]1c773ea12009-04-28 19:58:42772 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52773 EXPECT_TRUE(response != NULL);
774
775 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25776 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52777
778 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57779 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42780 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25781 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52782 }
783}
[email protected]3d2a59b2008-09-26 19:44:25784
785TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42786 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25787 KeepAliveConnectionResendRequestTest(read_failure);
788}
789
790TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42791 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25792 KeepAliveConnectionResendRequestTest(read_failure);
793}
794
795TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59796 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40797 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43798 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25799
[email protected]1c773ea12009-04-28 19:58:42800 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25801 request.method = "GET";
802 request.url = GURL("http://www.google.com/");
803 request.load_flags = 0;
804
805 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42806 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35807 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
808 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42809 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25810 };
[email protected]31a2bfe2010-02-09 08:03:39811 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59812 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25813
814 TestCompletionCallback callback;
815
[email protected]5a1d7ca2010-04-28 20:12:27816 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42817 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25818
819 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42820 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25821
[email protected]1c773ea12009-04-28 19:58:42822 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25823 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25824}
825
826// What do various browsers do when the server closes a non-keepalive
827// connection without sending any response header or body?
828//
829// IE7: error page
830// Safari 3.1.2 (Windows): error page
831// Firefox 3.0.1: blank page
832// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42833// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
834// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25835TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
836 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42837 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35838 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
839 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42840 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25841 };
[email protected]31a2bfe2010-02-09 08:03:39842 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
843 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42844 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25845}
[email protected]038e9a32008-10-08 22:40:16846
[email protected]fc31d6a42010-06-24 18:05:13847// Test that we correctly reuse a keep-alive connection after receiving a 304.
848TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
849 SessionDependencies session_deps;
850 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
851
852 HttpRequestInfo request;
853 request.method = "GET";
854 request.url = GURL("http://www.foo.com/");
855 request.load_flags = 0;
856
857 MockRead data1_reads[] = {
858 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
859 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
860 MockRead("hello"),
861 };
862 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
863 session_deps.socket_factory.AddSocketDataProvider(&data1);
864
865 MockRead data2_reads[] = {
866 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
867 };
868 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
869 session_deps.socket_factory.AddSocketDataProvider(&data2);
870
871 for (int i = 0; i < 2; ++i) {
872 TestCompletionCallback callback;
873
874 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
875
876 int rv = trans->Start(&request, &callback, BoundNetLog());
877 EXPECT_EQ(ERR_IO_PENDING, rv);
878
879 rv = callback.WaitForResult();
880 EXPECT_EQ(OK, rv);
881
882 const HttpResponseInfo* response = trans->GetResponseInfo();
883 EXPECT_TRUE(response != NULL);
884
885 EXPECT_TRUE(response->headers != NULL);
886 if (i == 0) {
887 EXPECT_EQ("HTTP/1.1 304 Not Modified",
888 response->headers->GetStatusLine());
889 // We intentionally don't read the response in this case, to reflect how
890 // HttpCache::Transaction uses HttpNetworkTransaction.
891 } else {
892 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
893 std::string response_data;
894 rv = ReadTransaction(trans.get(), &response_data);
895 EXPECT_EQ(OK, rv);
896 EXPECT_EQ("hello", response_data);
897 }
898 }
899}
900
[email protected]038e9a32008-10-08 22:40:16901// Test the request-challenge-retry sequence for basic auth.
902// (basic auth is the easiest to mock, because it has no randomness).
903TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59904 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40905 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43906 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16907
[email protected]1c773ea12009-04-28 19:58:42908 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16909 request.method = "GET";
910 request.url = GURL("http://www.google.com/");
911 request.load_flags = 0;
912
[email protected]f9ee6b52008-11-08 06:46:23913 MockWrite data_writes1[] = {
914 MockWrite("GET / HTTP/1.1\r\n"
915 "Host: www.google.com\r\n"
916 "Connection: keep-alive\r\n\r\n"),
917 };
918
[email protected]038e9a32008-10-08 22:40:16919 MockRead data_reads1[] = {
920 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
921 // Give a couple authenticate options (only the middle one is actually
922 // supported).
[email protected]22927ad2009-09-21 19:56:19923 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16924 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
925 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
926 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
927 // Large content-length -- won't matter, as connection will be reset.
928 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42929 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16930 };
931
932 // After calling trans->RestartWithAuth(), this is the request we should
933 // be issuing -- the final header line contains the credentials.
934 MockWrite data_writes2[] = {
935 MockWrite("GET / HTTP/1.1\r\n"
936 "Host: www.google.com\r\n"
937 "Connection: keep-alive\r\n"
938 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
939 };
940
941 // Lastly, the server responds with the actual content.
942 MockRead data_reads2[] = {
943 MockRead("HTTP/1.0 200 OK\r\n"),
944 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
945 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42946 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16947 };
948
[email protected]31a2bfe2010-02-09 08:03:39949 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
950 data_writes1, arraysize(data_writes1));
951 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
952 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59953 session_deps.socket_factory.AddSocketDataProvider(&data1);
954 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16955
956 TestCompletionCallback callback1;
957
[email protected]5a1d7ca2010-04-28 20:12:27958 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42959 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16960
961 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42962 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16963
[email protected]1c773ea12009-04-28 19:58:42964 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16965 EXPECT_FALSE(response == NULL);
966
967 // The password prompt info should have been set in response->auth_challenge.
968 EXPECT_FALSE(response->auth_challenge.get() == NULL);
969
[email protected]71e4573a2009-05-21 22:03:00970 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16971 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
972 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
973
974 TestCompletionCallback callback2;
975
[email protected]13c8a092010-07-29 06:15:44976 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:42977 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16978
979 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42980 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16981
982 response = trans->GetResponseInfo();
983 EXPECT_FALSE(response == NULL);
984 EXPECT_TRUE(response->auth_challenge.get() == NULL);
985 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16986}
987
[email protected]861fcd52009-08-26 02:33:46988TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
989 SessionDependencies session_deps;
990 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43991 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46992
993 HttpRequestInfo request;
994 request.method = "GET";
995 request.url = GURL("http://www.google.com/");
996 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
997
998 MockWrite data_writes[] = {
999 MockWrite("GET / HTTP/1.1\r\n"
1000 "Host: www.google.com\r\n"
1001 "Connection: keep-alive\r\n\r\n"),
1002 };
1003
1004 MockRead data_reads[] = {
1005 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1006 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1007 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1008 // Large content-length -- won't matter, as connection will be reset.
1009 MockRead("Content-Length: 10000\r\n\r\n"),
1010 MockRead(false, ERR_FAILED),
1011 };
1012
[email protected]31a2bfe2010-02-09 08:03:391013 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1014 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591015 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461016 TestCompletionCallback callback;
1017
[email protected]5a1d7ca2010-04-28 20:12:271018 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461019 EXPECT_EQ(ERR_IO_PENDING, rv);
1020
1021 rv = callback.WaitForResult();
1022 EXPECT_EQ(0, rv);
1023
1024 const HttpResponseInfo* response = trans->GetResponseInfo();
1025 ASSERT_FALSE(response == NULL);
1026 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1027}
1028
[email protected]2d2697f92009-02-18 21:00:321029// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1030// connection.
1031TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591032 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401033 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431034 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321035
[email protected]1c773ea12009-04-28 19:58:421036 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321037 request.method = "GET";
1038 request.url = GURL("http://www.google.com/");
1039 request.load_flags = 0;
1040
1041 MockWrite data_writes1[] = {
1042 MockWrite("GET / HTTP/1.1\r\n"
1043 "Host: www.google.com\r\n"
1044 "Connection: keep-alive\r\n\r\n"),
1045
1046 // After calling trans->RestartWithAuth(), this is the request we should
1047 // be issuing -- the final header line contains the credentials.
1048 MockWrite("GET / HTTP/1.1\r\n"
1049 "Host: www.google.com\r\n"
1050 "Connection: keep-alive\r\n"
1051 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1052 };
1053
1054 MockRead data_reads1[] = {
1055 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1056 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1057 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1058 MockRead("Content-Length: 14\r\n\r\n"),
1059 MockRead("Unauthorized\r\n"),
1060
1061 // Lastly, the server responds with the actual content.
1062 MockRead("HTTP/1.1 200 OK\r\n"),
1063 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1064 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421065 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321066 };
1067
[email protected]31a2bfe2010-02-09 08:03:391068 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1069 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591070 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321071
1072 TestCompletionCallback callback1;
1073
[email protected]5a1d7ca2010-04-28 20:12:271074 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421075 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321076
1077 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421078 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321079
[email protected]1c773ea12009-04-28 19:58:421080 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321081 EXPECT_FALSE(response == NULL);
1082
1083 // The password prompt info should have been set in response->auth_challenge.
1084 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1085
[email protected]71e4573a2009-05-21 22:03:001086 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321087 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1088 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1089
1090 TestCompletionCallback callback2;
1091
[email protected]13c8a092010-07-29 06:15:441092 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421093 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321094
1095 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421096 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321097
1098 response = trans->GetResponseInfo();
1099 EXPECT_FALSE(response == NULL);
1100 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1101 EXPECT_EQ(100, response->headers->GetContentLength());
1102}
1103
1104// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1105// connection and with no response body to drain.
1106TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591107 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401108 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431109 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321110
[email protected]1c773ea12009-04-28 19:58:421111 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321112 request.method = "GET";
1113 request.url = GURL("http://www.google.com/");
1114 request.load_flags = 0;
1115
1116 MockWrite data_writes1[] = {
1117 MockWrite("GET / HTTP/1.1\r\n"
1118 "Host: www.google.com\r\n"
1119 "Connection: keep-alive\r\n\r\n"),
1120
1121 // After calling trans->RestartWithAuth(), this is the request we should
1122 // be issuing -- the final header line contains the credentials.
1123 MockWrite("GET / HTTP/1.1\r\n"
1124 "Host: www.google.com\r\n"
1125 "Connection: keep-alive\r\n"
1126 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1127 };
1128
[email protected]2d2697f92009-02-18 21:00:321129 MockRead data_reads1[] = {
1130 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1131 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311132 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321133
1134 // Lastly, the server responds with the actual content.
1135 MockRead("HTTP/1.1 200 OK\r\n"),
1136 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1137 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421138 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321139 };
1140
[email protected]31a2bfe2010-02-09 08:03:391141 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1142 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591143 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321144
1145 TestCompletionCallback callback1;
1146
[email protected]5a1d7ca2010-04-28 20:12:271147 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421148 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321149
1150 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421151 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321152
[email protected]1c773ea12009-04-28 19:58:421153 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321154 EXPECT_FALSE(response == NULL);
1155
1156 // The password prompt info should have been set in response->auth_challenge.
1157 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1158
[email protected]71e4573a2009-05-21 22:03:001159 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321160 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1161 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1162
1163 TestCompletionCallback callback2;
1164
[email protected]13c8a092010-07-29 06:15:441165 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421166 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321167
1168 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421169 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321170
1171 response = trans->GetResponseInfo();
1172 EXPECT_FALSE(response == NULL);
1173 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1174 EXPECT_EQ(100, response->headers->GetContentLength());
1175}
1176
1177// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1178// connection and with a large response body to drain.
1179TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591180 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401181 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431182 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321183
[email protected]1c773ea12009-04-28 19:58:421184 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321185 request.method = "GET";
1186 request.url = GURL("http://www.google.com/");
1187 request.load_flags = 0;
1188
1189 MockWrite data_writes1[] = {
1190 MockWrite("GET / HTTP/1.1\r\n"
1191 "Host: www.google.com\r\n"
1192 "Connection: keep-alive\r\n\r\n"),
1193
1194 // After calling trans->RestartWithAuth(), this is the request we should
1195 // be issuing -- the final header line contains the credentials.
1196 MockWrite("GET / HTTP/1.1\r\n"
1197 "Host: www.google.com\r\n"
1198 "Connection: keep-alive\r\n"
1199 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1200 };
1201
1202 // Respond with 5 kb of response body.
1203 std::string large_body_string("Unauthorized");
1204 large_body_string.append(5 * 1024, ' ');
1205 large_body_string.append("\r\n");
1206
1207 MockRead data_reads1[] = {
1208 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1209 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1210 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1211 // 5134 = 12 + 5 * 1024 + 2
1212 MockRead("Content-Length: 5134\r\n\r\n"),
1213 MockRead(true, large_body_string.data(), large_body_string.size()),
1214
1215 // Lastly, the server responds with the actual content.
1216 MockRead("HTTP/1.1 200 OK\r\n"),
1217 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1218 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421219 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321220 };
1221
[email protected]31a2bfe2010-02-09 08:03:391222 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1223 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591224 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321225
1226 TestCompletionCallback callback1;
1227
[email protected]5a1d7ca2010-04-28 20:12:271228 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421229 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321230
1231 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421232 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321233
[email protected]1c773ea12009-04-28 19:58:421234 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321235 EXPECT_FALSE(response == NULL);
1236
1237 // The password prompt info should have been set in response->auth_challenge.
1238 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1239
[email protected]71e4573a2009-05-21 22:03:001240 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321241 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1242 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1243
1244 TestCompletionCallback callback2;
1245
[email protected]13c8a092010-07-29 06:15:441246 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421247 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321248
1249 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421250 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321251
1252 response = trans->GetResponseInfo();
1253 EXPECT_FALSE(response == NULL);
1254 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1255 EXPECT_EQ(100, response->headers->GetContentLength());
1256}
1257
1258// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311259// connection, but the server gets impatient and closes the connection.
1260TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1261 SessionDependencies session_deps;
1262 scoped_ptr<HttpTransaction> trans(
1263 new HttpNetworkTransaction(CreateSession(&session_deps)));
1264
1265 HttpRequestInfo request;
1266 request.method = "GET";
1267 request.url = GURL("http://www.google.com/");
1268 request.load_flags = 0;
1269
1270 MockWrite data_writes1[] = {
1271 MockWrite("GET / HTTP/1.1\r\n"
1272 "Host: www.google.com\r\n"
1273 "Connection: keep-alive\r\n\r\n"),
1274 // This simulates the seemingly successful write to a closed connection
1275 // if the bug is not fixed.
1276 MockWrite("GET / HTTP/1.1\r\n"
1277 "Host: www.google.com\r\n"
1278 "Connection: keep-alive\r\n"
1279 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1280 };
1281
1282 MockRead data_reads1[] = {
1283 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1284 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1285 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1286 MockRead("Content-Length: 14\r\n\r\n"),
1287 // Tell MockTCPClientSocket to simulate the server closing the connection.
1288 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1289 MockRead("Unauthorized\r\n"),
1290 MockRead(false, OK), // The server closes the connection.
1291 };
1292
1293 // After calling trans->RestartWithAuth(), this is the request we should
1294 // be issuing -- the final header line contains the credentials.
1295 MockWrite data_writes2[] = {
1296 MockWrite("GET / HTTP/1.1\r\n"
1297 "Host: www.google.com\r\n"
1298 "Connection: keep-alive\r\n"
1299 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1300 };
1301
1302 // Lastly, the server responds with the actual content.
1303 MockRead data_reads2[] = {
1304 MockRead("HTTP/1.1 200 OK\r\n"),
1305 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1306 MockRead("Content-Length: 100\r\n\r\n"),
1307 MockRead(false, OK),
1308 };
1309
[email protected]31a2bfe2010-02-09 08:03:391310 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1311 data_writes1, arraysize(data_writes1));
1312 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1313 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311314 session_deps.socket_factory.AddSocketDataProvider(&data1);
1315 session_deps.socket_factory.AddSocketDataProvider(&data2);
1316
1317 TestCompletionCallback callback1;
1318
[email protected]5a1d7ca2010-04-28 20:12:271319 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311320 EXPECT_EQ(ERR_IO_PENDING, rv);
1321
1322 rv = callback1.WaitForResult();
1323 EXPECT_EQ(OK, rv);
1324
1325 const HttpResponseInfo* response = trans->GetResponseInfo();
1326 EXPECT_FALSE(response == NULL);
1327
1328 // The password prompt info should have been set in response->auth_challenge.
1329 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1330
1331 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1332 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1333 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1334
1335 TestCompletionCallback callback2;
1336
[email protected]13c8a092010-07-29 06:15:441337 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311338 EXPECT_EQ(ERR_IO_PENDING, rv);
1339
1340 rv = callback2.WaitForResult();
1341 EXPECT_EQ(OK, rv);
1342
1343 response = trans->GetResponseInfo();
1344 ASSERT_FALSE(response == NULL);
1345 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1346 EXPECT_EQ(100, response->headers->GetContentLength());
1347}
1348
[email protected]394816e92010-08-03 07:38:591349// Test the request-challenge-retry sequence for basic auth, over a connection
1350// that requires a restart when setting up an SSL tunnel.
1351TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1352 // Configure against proxy server "myproxy:70".
1353 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1354 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1355 session_deps.net_log = log.bound().net_log();
1356 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1357
1358 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1359
1360 HttpRequestInfo request;
1361 request.method = "GET";
1362 request.url = GURL("https://www.google.com/");
1363 // when the no authentication data flag is set.
1364 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1365
1366 // Since we have proxy, should try to establish tunnel.
1367 MockWrite data_writes1[] = {
1368 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1369 "Host: www.google.com\r\n"
1370 "Proxy-Connection: keep-alive\r\n\r\n"),
1371
1372 // After calling trans->RestartWithAuth(), this is the request we should
1373 // be issuing -- the final header line contains the credentials.
1374 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1375 "Host: www.google.com\r\n"
1376 "Proxy-Connection: keep-alive\r\n"
1377 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1378
1379 MockWrite("GET / HTTP/1.1\r\n"
1380 "Host: www.google.com\r\n"
1381 "Connection: keep-alive\r\n\r\n"),
1382 };
1383
1384 // The proxy responds to the connect with a 407, using a persistent
1385 // connection.
1386 MockRead data_reads1[] = {
1387 // No credentials.
1388 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1389 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1390 MockRead("Proxy-Connection: close\r\n\r\n"),
1391
1392 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1393
1394 MockRead("HTTP/1.1 200 OK\r\n"),
1395 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1396 MockRead("Content-Length: 100\r\n\r\n"),
1397 MockRead(false, OK),
1398 };
1399
1400 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1401 data_writes1, arraysize(data_writes1));
1402 session_deps.socket_factory.AddSocketDataProvider(&data1);
1403 SSLSocketDataProvider ssl(true, OK);
1404 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1405
1406 TestCompletionCallback callback1;
1407
1408 int rv = trans->Start(&request, &callback1, log.bound());
1409 EXPECT_EQ(ERR_IO_PENDING, rv);
1410
1411 rv = callback1.WaitForResult();
1412 EXPECT_EQ(OK, rv);
1413 size_t pos = ExpectLogContainsSomewhere(
1414 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1415 NetLog::PHASE_NONE);
1416 ExpectLogContainsSomewhere(
1417 log.entries(), pos,
1418 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1419 NetLog::PHASE_NONE);
1420
1421 const HttpResponseInfo* response = trans->GetResponseInfo();
1422 ASSERT_FALSE(response == NULL);
1423
1424 EXPECT_EQ(407, response->headers->response_code());
1425 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1426
1427 // The password prompt info should have been set in response->auth_challenge.
1428 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1429
1430 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1431 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1432 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1433
1434 TestCompletionCallback callback2;
1435
1436 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1437 EXPECT_EQ(ERR_IO_PENDING, rv);
1438
1439 rv = callback2.WaitForResult();
1440 EXPECT_EQ(OK, rv);
1441
1442 response = trans->GetResponseInfo();
1443 ASSERT_FALSE(response == NULL);
1444
1445 EXPECT_TRUE(response->headers->IsKeepAlive());
1446 EXPECT_EQ(200, response->headers->response_code());
1447 EXPECT_EQ(100, response->headers->GetContentLength());
1448 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1449
1450 // The password prompt info should not be set.
1451 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1452}
1453
[email protected]11203f012009-11-12 23:02:311454// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321455// proxy connection, when setting up an SSL tunnel.
1456TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1457 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591458 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541459 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1460 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591461 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321462
[email protected]5695b8c2009-09-30 21:36:431463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321464
[email protected]1c773ea12009-04-28 19:58:421465 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321466 request.method = "GET";
1467 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461468 // Ensure that proxy authentication is attempted even
1469 // when the no authentication data flag is set.
1470 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321471
1472 // Since we have proxy, should try to establish tunnel.
1473 MockWrite data_writes1[] = {
1474 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451475 "Host: www.google.com\r\n"
1476 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321477
1478 // After calling trans->RestartWithAuth(), this is the request we should
1479 // be issuing -- the final header line contains the credentials.
1480 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1481 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451482 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321483 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1484 };
1485
1486 // The proxy responds to the connect with a 407, using a persistent
1487 // connection.
1488 MockRead data_reads1[] = {
1489 // No credentials.
1490 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1491 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1492 MockRead("Content-Length: 10\r\n\r\n"),
1493 MockRead("0123456789"),
1494
1495 // Wrong credentials (wrong password).
1496 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1497 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1498 MockRead("Content-Length: 10\r\n\r\n"),
1499 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421500 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321501 };
1502
[email protected]31a2bfe2010-02-09 08:03:391503 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1504 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591505 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321506
1507 TestCompletionCallback callback1;
1508
[email protected]dbb83db2010-05-11 18:13:391509 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421510 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321511
1512 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421513 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391514 size_t pos = ExpectLogContainsSomewhere(
1515 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1516 NetLog::PHASE_NONE);
1517 ExpectLogContainsSomewhere(
1518 log.entries(), pos,
1519 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1520 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321521
[email protected]1c773ea12009-04-28 19:58:421522 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321523 EXPECT_FALSE(response == NULL);
1524
1525 EXPECT_TRUE(response->headers->IsKeepAlive());
1526 EXPECT_EQ(407, response->headers->response_code());
1527 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421528 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321529
1530 // The password prompt info should have been set in response->auth_challenge.
1531 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1532
[email protected]71e4573a2009-05-21 22:03:001533 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321534 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1535 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1536
1537 TestCompletionCallback callback2;
1538
1539 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441540 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421541 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321542
1543 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421544 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321545
1546 response = trans->GetResponseInfo();
1547 EXPECT_FALSE(response == NULL);
1548
1549 EXPECT_TRUE(response->headers->IsKeepAlive());
1550 EXPECT_EQ(407, response->headers->response_code());
1551 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421552 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321553
1554 // The password prompt info should have been set in response->auth_challenge.
1555 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1556
[email protected]71e4573a2009-05-21 22:03:001557 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321558 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1559 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131560
[email protected]e60e47a2010-07-14 03:37:181561 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1562 // out of scope.
1563 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321564}
1565
[email protected]a8e9b162009-03-12 00:06:441566// Test that we don't read the response body when we fail to establish a tunnel,
1567// even if the user cancels the proxy's auth attempt.
1568TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1569 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591570 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441571
[email protected]e44de5d2009-06-05 20:12:451572 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441573
[email protected]5695b8c2009-09-30 21:36:431574 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441575
[email protected]1c773ea12009-04-28 19:58:421576 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441577 request.method = "GET";
1578 request.url = GURL("https://www.google.com/");
1579 request.load_flags = 0;
1580
1581 // Since we have proxy, should try to establish tunnel.
1582 MockWrite data_writes[] = {
1583 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451584 "Host: www.google.com\r\n"
1585 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441586 };
1587
1588 // The proxy responds to the connect with a 407.
1589 MockRead data_reads[] = {
1590 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1591 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1592 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421593 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441594 };
1595
[email protected]31a2bfe2010-02-09 08:03:391596 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1597 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591598 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441599
1600 TestCompletionCallback callback;
1601
[email protected]5a1d7ca2010-04-28 20:12:271602 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421603 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441604
1605 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421606 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441607
[email protected]1c773ea12009-04-28 19:58:421608 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441609 EXPECT_FALSE(response == NULL);
1610
1611 EXPECT_TRUE(response->headers->IsKeepAlive());
1612 EXPECT_EQ(407, response->headers->response_code());
1613 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421614 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441615
1616 std::string response_data;
1617 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421618 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181619
1620 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1621 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441622}
1623
[email protected]8fdbcd22010-05-05 02:54:521624// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1625// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1626TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1627 // We are using a DIRECT connection (i.e. no proxy) for this session.
1628 SessionDependencies session_deps;
1629 scoped_ptr<HttpTransaction> trans(
1630 new HttpNetworkTransaction(CreateSession(&session_deps)));
1631
1632 HttpRequestInfo request;
1633 request.method = "GET";
1634 request.url = GURL("http://www.google.com/");
1635 request.load_flags = 0;
1636
1637 MockWrite data_writes1[] = {
1638 MockWrite("GET / HTTP/1.1\r\n"
1639 "Host: www.google.com\r\n"
1640 "Connection: keep-alive\r\n\r\n"),
1641 };
1642
1643 MockRead data_reads1[] = {
1644 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1645 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1646 // Large content-length -- won't matter, as connection will be reset.
1647 MockRead("Content-Length: 10000\r\n\r\n"),
1648 MockRead(false, ERR_FAILED),
1649 };
1650
1651 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1652 data_writes1, arraysize(data_writes1));
1653 session_deps.socket_factory.AddSocketDataProvider(&data1);
1654
1655 TestCompletionCallback callback;
1656
1657 int rv = trans->Start(&request, &callback, BoundNetLog());
1658 EXPECT_EQ(ERR_IO_PENDING, rv);
1659
1660 rv = callback.WaitForResult();
1661 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1662}
1663
[email protected]ff007e162009-05-23 09:13:151664void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081665 const MockRead& status, int expected_status) {
1666 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591667 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081668
[email protected]228ff742009-06-05 01:19:591669 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081670
[email protected]5695b8c2009-09-30 21:36:431671 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081672
[email protected]1c773ea12009-04-28 19:58:421673 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081674 request.method = "GET";
1675 request.url = GURL("https://www.google.com/");
1676 request.load_flags = 0;
1677
1678 // Since we have proxy, should try to establish tunnel.
1679 MockWrite data_writes[] = {
1680 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451681 "Host: www.google.com\r\n"
1682 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081683 };
1684
1685 MockRead data_reads[] = {
1686 status,
1687 MockRead("Content-Length: 10\r\n\r\n"),
1688 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421689 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081690 };
1691
[email protected]31a2bfe2010-02-09 08:03:391692 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1693 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591694 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081695
1696 TestCompletionCallback callback;
1697
[email protected]5a1d7ca2010-04-28 20:12:271698 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421699 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081700
1701 rv = callback.WaitForResult();
1702 EXPECT_EQ(expected_status, rv);
1703}
1704
[email protected]ff007e162009-05-23 09:13:151705void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081706 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421707 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081708}
1709
1710TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1711 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1712}
1713
1714TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1715 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1716}
1717
1718TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1719 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1720}
1721
1722TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1723 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1724}
1725
1726TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1727 ConnectStatusHelper(
1728 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1729}
1730
1731TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1732 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1733}
1734
1735TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1736 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1737}
1738
1739TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1740 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1741}
1742
1743TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1744 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1745}
1746
1747TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1748 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1749}
1750
1751TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1752 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1753}
1754
1755TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1756 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1757}
1758
1759TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1760 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1761}
1762
1763TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1764 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1765}
1766
1767TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1768 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1769}
1770
1771TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1772 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1773}
1774
1775TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1776 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1777}
1778
1779TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1780 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1781}
1782
1783TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1784 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1785}
1786
1787TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1788 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1789}
1790
1791TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1792 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1793}
1794
1795TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1796 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1797}
1798
1799TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1800 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1801}
1802
1803TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1804 ConnectStatusHelperWithExpectedStatus(
1805 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541806 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081807}
1808
1809TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1810 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1811}
1812
1813TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1814 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1815}
1816
1817TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1818 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1819}
1820
1821TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1822 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1823}
1824
1825TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1826 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1827}
1828
1829TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1830 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1831}
1832
1833TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1834 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1835}
1836
1837TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1838 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1839}
1840
1841TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1842 ConnectStatusHelper(
1843 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1844}
1845
1846TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1847 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1848}
1849
1850TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1851 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1852}
1853
1854TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1855 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1856}
1857
1858TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1859 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1860}
1861
1862TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1863 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1864}
1865
1866TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1867 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1868}
1869
1870TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1871 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1872}
1873
[email protected]038e9a32008-10-08 22:40:161874// Test the flow when both the proxy server AND origin server require
1875// authentication. Again, this uses basic auth for both since that is
1876// the simplest to mock.
1877TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591878 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011879
[email protected]038e9a32008-10-08 22:40:161880 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421881 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431882 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161883
[email protected]1c773ea12009-04-28 19:58:421884 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161885 request.method = "GET";
1886 request.url = GURL("http://www.google.com/");
1887 request.load_flags = 0;
1888
[email protected]f9ee6b52008-11-08 06:46:231889 MockWrite data_writes1[] = {
1890 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1891 "Host: www.google.com\r\n"
1892 "Proxy-Connection: keep-alive\r\n\r\n"),
1893 };
1894
[email protected]038e9a32008-10-08 22:40:161895 MockRead data_reads1[] = {
1896 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1897 // Give a couple authenticate options (only the middle one is actually
1898 // supported).
[email protected]22927ad2009-09-21 19:56:191899 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161900 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1901 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1902 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1903 // Large content-length -- won't matter, as connection will be reset.
1904 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421905 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161906 };
1907
1908 // After calling trans->RestartWithAuth() the first time, this is the
1909 // request we should be issuing -- the final header line contains the
1910 // proxy's credentials.
1911 MockWrite data_writes2[] = {
1912 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1913 "Host: www.google.com\r\n"
1914 "Proxy-Connection: keep-alive\r\n"
1915 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1916 };
1917
1918 // Now the proxy server lets the request pass through to origin server.
1919 // The origin server responds with a 401.
1920 MockRead data_reads2[] = {
1921 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1922 // Note: We are using the same realm-name as the proxy server. This is
1923 // completely valid, as realms are unique across hosts.
1924 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1925 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1926 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421927 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161928 };
1929
1930 // After calling trans->RestartWithAuth() the second time, we should send
1931 // the credentials for both the proxy and origin server.
1932 MockWrite data_writes3[] = {
1933 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1934 "Host: www.google.com\r\n"
1935 "Proxy-Connection: keep-alive\r\n"
1936 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1937 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1938 };
1939
1940 // Lastly we get the desired content.
1941 MockRead data_reads3[] = {
1942 MockRead("HTTP/1.0 200 OK\r\n"),
1943 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1944 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421945 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161946 };
1947
[email protected]31a2bfe2010-02-09 08:03:391948 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1949 data_writes1, arraysize(data_writes1));
1950 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1951 data_writes2, arraysize(data_writes2));
1952 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1953 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591954 session_deps.socket_factory.AddSocketDataProvider(&data1);
1955 session_deps.socket_factory.AddSocketDataProvider(&data2);
1956 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161957
1958 TestCompletionCallback callback1;
1959
[email protected]5a1d7ca2010-04-28 20:12:271960 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421961 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161962
1963 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421964 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161965
[email protected]1c773ea12009-04-28 19:58:421966 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161967 EXPECT_FALSE(response == NULL);
1968
1969 // The password prompt info should have been set in response->auth_challenge.
1970 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1971
[email protected]71e4573a2009-05-21 22:03:001972 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161973 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1974 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1975
1976 TestCompletionCallback callback2;
1977
[email protected]13c8a092010-07-29 06:15:441978 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421979 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161980
1981 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421982 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161983
1984 response = trans->GetResponseInfo();
1985 EXPECT_FALSE(response == NULL);
1986 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1987
[email protected]71e4573a2009-05-21 22:03:001988 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161989 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1990 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1991
1992 TestCompletionCallback callback3;
1993
[email protected]13c8a092010-07-29 06:15:441994 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:421995 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161996
1997 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421998 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161999
2000 response = trans->GetResponseInfo();
2001 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2002 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162003}
[email protected]4ddaf2502008-10-23 18:26:192004
[email protected]ea9dc9a2009-09-05 00:43:322005// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2006// can't hook into its internals to cause it to generate predictable NTLM
2007// authorization headers.
2008#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292009// The NTLM authentication unit tests were generated by capturing the HTTP
2010// requests and responses using Fiddler 2 and inspecting the generated random
2011// bytes in the debugger.
2012
2013// Enter the correct password and authenticate successfully.
2014TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422015 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112016 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592017 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402018 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432019 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:242020
[email protected]1c773ea12009-04-28 19:58:422021 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242022 request.method = "GET";
2023 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2024 request.load_flags = 0;
2025
2026 MockWrite data_writes1[] = {
2027 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2028 "Host: 172.22.68.17\r\n"
2029 "Connection: keep-alive\r\n\r\n"),
2030 };
2031
2032 MockRead data_reads1[] = {
2033 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042034 // Negotiate and NTLM are often requested together. However, we only want
2035 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2036 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242037 MockRead("WWW-Authenticate: NTLM\r\n"),
2038 MockRead("Connection: close\r\n"),
2039 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362040 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242041 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422042 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242043 };
2044
2045 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222046 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242047 // request we should be issuing -- the final header line contains a Type
2048 // 1 message.
2049 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2050 "Host: 172.22.68.17\r\n"
2051 "Connection: keep-alive\r\n"
2052 "Authorization: NTLM "
2053 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2054
2055 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2056 // (the credentials for the origin server). The second request continues
2057 // on the same connection.
2058 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2059 "Host: 172.22.68.17\r\n"
2060 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292061 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2062 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2063 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2064 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2065 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242066 };
2067
2068 MockRead data_reads2[] = {
2069 // The origin server responds with a Type 2 message.
2070 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2071 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292072 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242073 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2074 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2075 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2076 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2077 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2078 "BtAAAAAAA=\r\n"),
2079 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362080 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242081 MockRead("You are not authorized to view this page\r\n"),
2082
2083 // Lastly we get the desired content.
2084 MockRead("HTTP/1.1 200 OK\r\n"),
2085 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2086 MockRead("Content-Length: 13\r\n\r\n"),
2087 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422088 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242089 };
2090
[email protected]31a2bfe2010-02-09 08:03:392091 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2092 data_writes1, arraysize(data_writes1));
2093 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2094 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592095 session_deps.socket_factory.AddSocketDataProvider(&data1);
2096 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242097
2098 TestCompletionCallback callback1;
2099
[email protected]5a1d7ca2010-04-28 20:12:272100 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422101 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242102
2103 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422104 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242105
[email protected]0757e7702009-03-27 04:00:222106 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2107 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442108 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422109 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222110 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422111 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222112 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2113
[email protected]1c773ea12009-04-28 19:58:422114 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042115 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242116
[email protected]aef04272010-06-28 18:03:042117 // The password prompt info should have been set in
2118 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242119 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2120
[email protected]71e4573a2009-05-21 22:03:002121 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242122 EXPECT_EQ(L"", response->auth_challenge->realm);
2123 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2124
[email protected]0757e7702009-03-27 04:00:222125 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242126
[email protected]13c8a092010-07-29 06:15:442127 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422128 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242129
[email protected]0757e7702009-03-27 04:00:222130 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422131 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242132
2133 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042134 ASSERT_FALSE(response == NULL);
2135
[email protected]3f918782009-02-28 01:29:242136 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2137 EXPECT_EQ(13, response->headers->GetContentLength());
2138}
2139
[email protected]385a4672009-03-11 22:21:292140// Enter a wrong password, and then the correct one.
2141TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422142 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112143 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592144 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402145 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432146 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:292147
[email protected]1c773ea12009-04-28 19:58:422148 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292149 request.method = "GET";
2150 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2151 request.load_flags = 0;
2152
2153 MockWrite data_writes1[] = {
2154 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2155 "Host: 172.22.68.17\r\n"
2156 "Connection: keep-alive\r\n\r\n"),
2157 };
2158
2159 MockRead data_reads1[] = {
2160 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042161 // Negotiate and NTLM are often requested together. However, we only want
2162 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2163 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292164 MockRead("WWW-Authenticate: NTLM\r\n"),
2165 MockRead("Connection: close\r\n"),
2166 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362167 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292168 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422169 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292170 };
2171
2172 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222173 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292174 // request we should be issuing -- the final header line contains a Type
2175 // 1 message.
2176 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2177 "Host: 172.22.68.17\r\n"
2178 "Connection: keep-alive\r\n"
2179 "Authorization: NTLM "
2180 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2181
2182 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2183 // (the credentials for the origin server). The second request continues
2184 // on the same connection.
2185 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2186 "Host: 172.22.68.17\r\n"
2187 "Connection: keep-alive\r\n"
2188 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2189 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2190 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2191 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2192 "4Ww7b7E=\r\n\r\n"),
2193 };
2194
2195 MockRead data_reads2[] = {
2196 // The origin server responds with a Type 2 message.
2197 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2198 MockRead("WWW-Authenticate: NTLM "
2199 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2200 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2201 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2202 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2203 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2204 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2205 "BtAAAAAAA=\r\n"),
2206 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362207 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292208 MockRead("You are not authorized to view this page\r\n"),
2209
2210 // Wrong password.
2211 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292212 MockRead("WWW-Authenticate: NTLM\r\n"),
2213 MockRead("Connection: close\r\n"),
2214 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362215 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292216 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422217 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292218 };
2219
2220 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222221 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292222 // request we should be issuing -- the final header line contains a Type
2223 // 1 message.
2224 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2225 "Host: 172.22.68.17\r\n"
2226 "Connection: keep-alive\r\n"
2227 "Authorization: NTLM "
2228 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2229
2230 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2231 // (the credentials for the origin server). The second request continues
2232 // on the same connection.
2233 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2234 "Host: 172.22.68.17\r\n"
2235 "Connection: keep-alive\r\n"
2236 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2237 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2238 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2239 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2240 "+4MUm7c=\r\n\r\n"),
2241 };
2242
2243 MockRead data_reads3[] = {
2244 // The origin server responds with a Type 2 message.
2245 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2246 MockRead("WWW-Authenticate: NTLM "
2247 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2248 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2249 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2250 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2251 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2252 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2253 "BtAAAAAAA=\r\n"),
2254 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362255 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292256 MockRead("You are not authorized to view this page\r\n"),
2257
2258 // Lastly we get the desired content.
2259 MockRead("HTTP/1.1 200 OK\r\n"),
2260 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2261 MockRead("Content-Length: 13\r\n\r\n"),
2262 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422263 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292264 };
2265
[email protected]31a2bfe2010-02-09 08:03:392266 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2267 data_writes1, arraysize(data_writes1));
2268 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2269 data_writes2, arraysize(data_writes2));
2270 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2271 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592272 session_deps.socket_factory.AddSocketDataProvider(&data1);
2273 session_deps.socket_factory.AddSocketDataProvider(&data2);
2274 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292275
2276 TestCompletionCallback callback1;
2277
[email protected]5a1d7ca2010-04-28 20:12:272278 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422279 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292280
2281 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422282 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292283
[email protected]0757e7702009-03-27 04:00:222284 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292285 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442286 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422287 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292288 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422289 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222290 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292291
[email protected]1c773ea12009-04-28 19:58:422292 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292293 EXPECT_FALSE(response == NULL);
2294
2295 // The password prompt info should have been set in response->auth_challenge.
2296 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2297
[email protected]71e4573a2009-05-21 22:03:002298 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292299 EXPECT_EQ(L"", response->auth_challenge->realm);
2300 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2301
2302 TestCompletionCallback callback3;
2303
[email protected]0757e7702009-03-27 04:00:222304 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442305 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422306 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292307
2308 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422309 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292310
[email protected]0757e7702009-03-27 04:00:222311 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2312 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442313 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422314 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222315 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422316 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222317 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2318
2319 response = trans->GetResponseInfo();
2320 EXPECT_FALSE(response == NULL);
2321
2322 // The password prompt info should have been set in response->auth_challenge.
2323 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2324
[email protected]71e4573a2009-05-21 22:03:002325 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222326 EXPECT_EQ(L"", response->auth_challenge->realm);
2327 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2328
2329 TestCompletionCallback callback5;
2330
2331 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442332 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422333 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222334
2335 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422336 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222337
[email protected]385a4672009-03-11 22:21:292338 response = trans->GetResponseInfo();
2339 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2340 EXPECT_EQ(13, response->headers->GetContentLength());
2341}
[email protected]ea9dc9a2009-09-05 00:43:322342#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292343
[email protected]4ddaf2502008-10-23 18:26:192344// Test reading a server response which has only headers, and no body.
2345// After some maximum number of bytes is consumed, the transaction should
2346// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2347TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592348 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402349 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432350 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192351
[email protected]1c773ea12009-04-28 19:58:422352 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192353 request.method = "GET";
2354 request.url = GURL("http://www.google.com/");
2355 request.load_flags = 0;
2356
[email protected]b75b7b2f2009-10-06 00:54:532357 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432358 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532359 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192360
2361 MockRead data_reads[] = {
2362 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432363 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192364 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422365 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192366 };
[email protected]31a2bfe2010-02-09 08:03:392367 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592368 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192369
2370 TestCompletionCallback callback;
2371
[email protected]5a1d7ca2010-04-28 20:12:272372 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422373 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192374
2375 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422376 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192377
[email protected]1c773ea12009-04-28 19:58:422378 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192379 EXPECT_TRUE(response == NULL);
2380}
[email protected]f4e426b2008-11-05 00:24:492381
2382// Make sure that we don't try to reuse a TCPClientSocket when failing to
2383// establish tunnel.
2384// http://code.google.com/p/chromium/issues/detail?id=3772
2385TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2386 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592387 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012388
[email protected]228ff742009-06-05 01:19:592389 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492390
[email protected]5695b8c2009-09-30 21:36:432391 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492392
[email protected]1c773ea12009-04-28 19:58:422393 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492394 request.method = "GET";
2395 request.url = GURL("https://www.google.com/");
2396 request.load_flags = 0;
2397
2398 // Since we have proxy, should try to establish tunnel.
2399 MockWrite data_writes1[] = {
2400 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452401 "Host: www.google.com\r\n"
2402 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492403 };
2404
[email protected]77848d12008-11-14 00:00:222405 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492406 // connection. Usually a proxy would return 501 (not implemented),
2407 // or 200 (tunnel established).
2408 MockRead data_reads1[] = {
2409 MockRead("HTTP/1.1 404 Not Found\r\n"),
2410 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422411 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492412 };
2413
[email protected]31a2bfe2010-02-09 08:03:392414 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2415 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592416 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492417
2418 TestCompletionCallback callback1;
2419
[email protected]5a1d7ca2010-04-28 20:12:272420 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422421 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492422
2423 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422424 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492425
[email protected]1c773ea12009-04-28 19:58:422426 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082427 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492428
[email protected]b4404c02009-04-10 16:38:522429 // Empty the current queue. This is necessary because idle sockets are
2430 // added to the connection pool asynchronously with a PostTask.
2431 MessageLoop::current()->RunAllPending();
2432
[email protected]f4e426b2008-11-05 00:24:492433 // We now check to make sure the TCPClientSocket was not added back to
2434 // the pool.
[email protected]a937a06d2009-08-19 21:19:242435 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492436 trans.reset();
[email protected]b4404c02009-04-10 16:38:522437 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492438 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242439 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492440}
[email protected]372d34a2008-11-05 21:30:512441
[email protected]1b157c02009-04-21 01:55:402442// Make sure that we recycle a socket after reading all of the response body.
2443TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592444 SessionDependencies session_deps;
2445 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402446
[email protected]5695b8c2009-09-30 21:36:432447 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402448
[email protected]1c773ea12009-04-28 19:58:422449 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402450 request.method = "GET";
2451 request.url = GURL("http://www.google.com/");
2452 request.load_flags = 0;
2453
2454 MockRead data_reads[] = {
2455 // A part of the response body is received with the response headers.
2456 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2457 // The rest of the response body is received in two parts.
2458 MockRead("lo"),
2459 MockRead(" world"),
2460 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422461 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402462 };
2463
[email protected]31a2bfe2010-02-09 08:03:392464 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592465 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402466
2467 TestCompletionCallback callback;
2468
[email protected]5a1d7ca2010-04-28 20:12:272469 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422470 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402471
2472 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422473 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402474
[email protected]1c773ea12009-04-28 19:58:422475 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402476 EXPECT_TRUE(response != NULL);
2477
2478 EXPECT_TRUE(response->headers != NULL);
2479 std::string status_line = response->headers->GetStatusLine();
2480 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2481
[email protected]a937a06d2009-08-19 21:19:242482 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402483
2484 std::string response_data;
2485 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422486 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402487 EXPECT_EQ("hello world", response_data);
2488
2489 // Empty the current queue. This is necessary because idle sockets are
2490 // added to the connection pool asynchronously with a PostTask.
2491 MessageLoop::current()->RunAllPending();
2492
2493 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242494 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402495}
2496
[email protected]76a505b2010-08-25 06:23:002497// Make sure that we recycle a SSL socket after reading all of the response
2498// body.
2499TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
2500 SessionDependencies session_deps;
2501 HttpRequestInfo request;
2502 request.method = "GET";
2503 request.url = GURL("https://www.google.com/");
2504 request.load_flags = 0;
2505
2506 MockWrite data_writes[] = {
2507 MockWrite("GET / HTTP/1.1\r\n"
2508 "Host: www.google.com\r\n"
2509 "Connection: keep-alive\r\n\r\n"),
2510 };
2511
2512 MockRead data_reads[] = {
2513 MockRead("HTTP/1.1 200 OK\r\n"),
2514 MockRead("Content-Length: 11\r\n\r\n"),
2515 MockRead("hello world"),
2516 MockRead(false, OK),
2517 };
2518
2519 SSLSocketDataProvider ssl(true, OK);
2520 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2521
2522 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2523 data_writes, arraysize(data_writes));
2524 session_deps.socket_factory.AddSocketDataProvider(&data);
2525
2526 TestCompletionCallback callback;
2527
2528 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2529 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2530
2531 int rv = trans->Start(&request, &callback, BoundNetLog());
2532
2533 EXPECT_EQ(ERR_IO_PENDING, rv);
2534 EXPECT_EQ(OK, callback.WaitForResult());
2535
2536 const HttpResponseInfo* response = trans->GetResponseInfo();
2537 ASSERT_TRUE(response != NULL);
2538 ASSERT_TRUE(response->headers != NULL);
2539 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2540
2541 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2542
2543 std::string response_data;
2544 rv = ReadTransaction(trans.get(), &response_data);
2545 EXPECT_EQ(OK, rv);
2546 EXPECT_EQ("hello world", response_data);
2547
2548 // Empty the current queue. This is necessary because idle sockets are
2549 // added to the connection pool asynchronously with a PostTask.
2550 MessageLoop::current()->RunAllPending();
2551
2552 // We now check to make sure the socket was added back to the pool.
2553 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2554}
2555
2556// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
2557// from the pool and make sure that we recover okay.
2558TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
2559 SessionDependencies session_deps;
2560 HttpRequestInfo request;
2561 request.method = "GET";
2562 request.url = GURL("https://www.google.com/");
2563 request.load_flags = 0;
2564
2565 MockWrite data_writes[] = {
2566 MockWrite("GET / HTTP/1.1\r\n"
2567 "Host: www.google.com\r\n"
2568 "Connection: keep-alive\r\n\r\n"),
2569 MockWrite("GET / HTTP/1.1\r\n"
2570 "Host: www.google.com\r\n"
2571 "Connection: keep-alive\r\n\r\n"),
2572 };
2573
2574 MockRead data_reads[] = {
2575 MockRead("HTTP/1.1 200 OK\r\n"),
2576 MockRead("Content-Length: 11\r\n\r\n"),
2577 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2578 MockRead("hello world"),
2579 MockRead(true, 0, 0) // EOF
2580 };
2581
2582 SSLSocketDataProvider ssl(true, OK);
2583 SSLSocketDataProvider ssl2(true, OK);
2584 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2585 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2586
2587 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2588 data_writes, arraysize(data_writes));
2589 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
2590 data_writes, arraysize(data_writes));
2591 session_deps.socket_factory.AddSocketDataProvider(&data);
2592 session_deps.socket_factory.AddSocketDataProvider(&data2);
2593
2594 TestCompletionCallback callback;
2595
2596 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2597 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2598
2599 int rv = trans->Start(&request, &callback, BoundNetLog());
2600
2601 EXPECT_EQ(ERR_IO_PENDING, rv);
2602 EXPECT_EQ(OK, callback.WaitForResult());
2603
2604 const HttpResponseInfo* response = trans->GetResponseInfo();
2605 ASSERT_TRUE(response != NULL);
2606 ASSERT_TRUE(response->headers != NULL);
2607 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2608
2609 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2610
2611 std::string response_data;
2612 rv = ReadTransaction(trans.get(), &response_data);
2613 EXPECT_EQ(OK, rv);
2614 EXPECT_EQ("hello world", response_data);
2615
2616 // Empty the current queue. This is necessary because idle sockets are
2617 // added to the connection pool asynchronously with a PostTask.
2618 MessageLoop::current()->RunAllPending();
2619
2620 // We now check to make sure the socket was added back to the pool.
2621 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2622
2623 // Now start the second transaction, which should reuse the previous socket.
2624
2625 trans.reset(new HttpNetworkTransaction(session));
2626
2627 rv = trans->Start(&request, &callback, BoundNetLog());
2628
2629 EXPECT_EQ(ERR_IO_PENDING, rv);
2630 EXPECT_EQ(OK, callback.WaitForResult());
2631
2632 response = trans->GetResponseInfo();
2633 ASSERT_TRUE(response != NULL);
2634 ASSERT_TRUE(response->headers != NULL);
2635 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2636
2637 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2638
2639 rv = ReadTransaction(trans.get(), &response_data);
2640 EXPECT_EQ(OK, rv);
2641 EXPECT_EQ("hello world", response_data);
2642
2643 // Empty the current queue. This is necessary because idle sockets are
2644 // added to the connection pool asynchronously with a PostTask.
2645 MessageLoop::current()->RunAllPending();
2646
2647 // We now check to make sure the socket was added back to the pool.
2648 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2649}
2650
[email protected]b4404c02009-04-10 16:38:522651// Make sure that we recycle a socket after a zero-length response.
2652// http://crbug.com/9880
2653TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592654 SessionDependencies session_deps;
2655 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522656
[email protected]5695b8c2009-09-30 21:36:432657 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522658
[email protected]1c773ea12009-04-28 19:58:422659 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522660 request.method = "GET";
2661 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2662 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2663 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2664 "rt=prt.2642,ol.2649,xjs.2951");
2665 request.load_flags = 0;
2666
2667 MockRead data_reads[] = {
2668 MockRead("HTTP/1.1 204 No Content\r\n"
2669 "Content-Length: 0\r\n"
2670 "Content-Type: text/html\r\n\r\n"),
2671 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422672 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522673 };
2674
[email protected]31a2bfe2010-02-09 08:03:392675 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592676 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522677
2678 TestCompletionCallback callback;
2679
[email protected]5a1d7ca2010-04-28 20:12:272680 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422681 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522682
2683 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422684 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522685
[email protected]1c773ea12009-04-28 19:58:422686 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522687 EXPECT_TRUE(response != NULL);
2688
2689 EXPECT_TRUE(response->headers != NULL);
2690 std::string status_line = response->headers->GetStatusLine();
2691 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2692
[email protected]a937a06d2009-08-19 21:19:242693 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522694
2695 std::string response_data;
2696 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422697 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522698 EXPECT_EQ("", response_data);
2699
2700 // Empty the current queue. This is necessary because idle sockets are
2701 // added to the connection pool asynchronously with a PostTask.
2702 MessageLoop::current()->RunAllPending();
2703
2704 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242705 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522706}
2707
[email protected]372d34a2008-11-05 21:30:512708TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422709 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512710 // Transaction 1: a GET request that succeeds. The socket is recycled
2711 // after use.
2712 request[0].method = "GET";
2713 request[0].url = GURL("http://www.google.com/");
2714 request[0].load_flags = 0;
2715 // Transaction 2: a POST request. Reuses the socket kept alive from
2716 // transaction 1. The first attempts fails when writing the POST data.
2717 // This causes the transaction to retry with a new socket. The second
2718 // attempt succeeds.
2719 request[1].method = "POST";
2720 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422721 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512722 request[1].upload_data->AppendBytes("foo", 3);
2723 request[1].load_flags = 0;
2724
[email protected]228ff742009-06-05 01:19:592725 SessionDependencies session_deps;
2726 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512727
2728 // The first socket is used for transaction 1 and the first attempt of
2729 // transaction 2.
2730
2731 // The response of transaction 1.
2732 MockRead data_reads1[] = {
2733 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2734 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422735 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512736 };
2737 // The mock write results of transaction 1 and the first attempt of
2738 // transaction 2.
2739 MockWrite data_writes1[] = {
2740 MockWrite(false, 64), // GET
2741 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422742 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512743 };
[email protected]31a2bfe2010-02-09 08:03:392744 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2745 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512746
2747 // The second socket is used for the second attempt of transaction 2.
2748
2749 // The response of transaction 2.
2750 MockRead data_reads2[] = {
2751 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2752 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422753 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512754 };
2755 // The mock write results of the second attempt of transaction 2.
2756 MockWrite data_writes2[] = {
2757 MockWrite(false, 93), // POST
2758 MockWrite(false, 3), // POST data
2759 };
[email protected]31a2bfe2010-02-09 08:03:392760 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2761 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512762
[email protected]5ecc992a42009-11-11 01:41:592763 session_deps.socket_factory.AddSocketDataProvider(&data1);
2764 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512765
2766 const char* kExpectedResponseData[] = {
2767 "hello world", "welcome"
2768 };
2769
2770 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422771 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432772 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512773
2774 TestCompletionCallback callback;
2775
[email protected]5a1d7ca2010-04-28 20:12:272776 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422777 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512778
2779 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422780 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512781
[email protected]1c773ea12009-04-28 19:58:422782 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512783 EXPECT_TRUE(response != NULL);
2784
2785 EXPECT_TRUE(response->headers != NULL);
2786 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2787
2788 std::string response_data;
2789 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422790 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512791 EXPECT_EQ(kExpectedResponseData[i], response_data);
2792 }
2793}
[email protected]f9ee6b52008-11-08 06:46:232794
2795// Test the request-challenge-retry sequence for basic auth when there is
2796// an identity in the URL. The request should be sent as normal, but when
2797// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322798TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592799 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402800 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432801 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232802
[email protected]1c773ea12009-04-28 19:58:422803 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232804 request.method = "GET";
2805 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292806 request.url = GURL("http://foo:b@[email protected]/");
2807
2808 // The password contains an escaped character -- for this test to pass it
2809 // will need to be unescaped by HttpNetworkTransaction.
2810 EXPECT_EQ("b%40r", request.url.password());
2811
[email protected]ea9dc9a2009-09-05 00:43:322812 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232813
2814 MockWrite data_writes1[] = {
2815 MockWrite("GET / HTTP/1.1\r\n"
2816 "Host: www.google.com\r\n"
2817 "Connection: keep-alive\r\n\r\n"),
2818 };
2819
2820 MockRead data_reads1[] = {
2821 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2822 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2823 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422824 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232825 };
2826
2827 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322828 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232829 MockWrite data_writes2[] = {
2830 MockWrite("GET / HTTP/1.1\r\n"
2831 "Host: www.google.com\r\n"
2832 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292833 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232834 };
2835
2836 MockRead data_reads2[] = {
2837 MockRead("HTTP/1.0 200 OK\r\n"),
2838 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422839 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232840 };
2841
[email protected]31a2bfe2010-02-09 08:03:392842 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2843 data_writes1, arraysize(data_writes1));
2844 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2845 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592846 session_deps.socket_factory.AddSocketDataProvider(&data1);
2847 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232848
2849 TestCompletionCallback callback1;
2850
[email protected]5a1d7ca2010-04-28 20:12:272851 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422852 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232853
2854 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422855 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232856
[email protected]0757e7702009-03-27 04:00:222857 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2858 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442859 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422860 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222861 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422862 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222863 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2864
[email protected]1c773ea12009-04-28 19:58:422865 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232866 EXPECT_FALSE(response == NULL);
2867
2868 // There is no challenge info, since the identity in URL worked.
2869 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2870
2871 EXPECT_EQ(100, response->headers->GetContentLength());
2872
2873 // Empty the current queue.
2874 MessageLoop::current()->RunAllPending();
2875}
2876
[email protected]ea9dc9a2009-09-05 00:43:322877// Test the request-challenge-retry sequence for basic auth when there is
2878// an incorrect identity in the URL. The identity from the URL should be used
2879// only once.
2880TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2881 SessionDependencies session_deps;
2882 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432883 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322884
2885 HttpRequestInfo request;
2886 request.method = "GET";
2887 // Note: the URL has a username:password in it. The password "baz" is
2888 // wrong (should be "bar").
2889 request.url = GURL("http://foo:[email protected]/");
2890
2891 request.load_flags = LOAD_NORMAL;
2892
2893 MockWrite data_writes1[] = {
2894 MockWrite("GET / HTTP/1.1\r\n"
2895 "Host: www.google.com\r\n"
2896 "Connection: keep-alive\r\n\r\n"),
2897 };
2898
2899 MockRead data_reads1[] = {
2900 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2901 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2902 MockRead("Content-Length: 10\r\n\r\n"),
2903 MockRead(false, ERR_FAILED),
2904 };
2905
2906 // After the challenge above, the transaction will be restarted using the
2907 // identity from the url (foo, baz) to answer the challenge.
2908 MockWrite data_writes2[] = {
2909 MockWrite("GET / HTTP/1.1\r\n"
2910 "Host: www.google.com\r\n"
2911 "Connection: keep-alive\r\n"
2912 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2913 };
2914
2915 MockRead data_reads2[] = {
2916 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2917 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2918 MockRead("Content-Length: 10\r\n\r\n"),
2919 MockRead(false, ERR_FAILED),
2920 };
2921
2922 // After the challenge above, the transaction will be restarted using the
2923 // identity supplied by the user (foo, bar) to answer the challenge.
2924 MockWrite data_writes3[] = {
2925 MockWrite("GET / HTTP/1.1\r\n"
2926 "Host: www.google.com\r\n"
2927 "Connection: keep-alive\r\n"
2928 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2929 };
2930
2931 MockRead data_reads3[] = {
2932 MockRead("HTTP/1.0 200 OK\r\n"),
2933 MockRead("Content-Length: 100\r\n\r\n"),
2934 MockRead(false, OK),
2935 };
2936
[email protected]31a2bfe2010-02-09 08:03:392937 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2938 data_writes1, arraysize(data_writes1));
2939 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2940 data_writes2, arraysize(data_writes2));
2941 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2942 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592943 session_deps.socket_factory.AddSocketDataProvider(&data1);
2944 session_deps.socket_factory.AddSocketDataProvider(&data2);
2945 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322946
2947 TestCompletionCallback callback1;
2948
[email protected]5a1d7ca2010-04-28 20:12:272949 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322950 EXPECT_EQ(ERR_IO_PENDING, rv);
2951
2952 rv = callback1.WaitForResult();
2953 EXPECT_EQ(OK, rv);
2954
2955 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2956 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442957 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:322958 EXPECT_EQ(ERR_IO_PENDING, rv);
2959 rv = callback2.WaitForResult();
2960 EXPECT_EQ(OK, rv);
2961 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2962
2963 const HttpResponseInfo* response = trans->GetResponseInfo();
2964 EXPECT_FALSE(response == NULL);
2965 // The password prompt info should have been set in response->auth_challenge.
2966 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2967
2968 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2969 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2970 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2971
2972 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:442973 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:322974 EXPECT_EQ(ERR_IO_PENDING, rv);
2975 rv = callback3.WaitForResult();
2976 EXPECT_EQ(OK, rv);
2977 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2978
2979 response = trans->GetResponseInfo();
2980 EXPECT_FALSE(response == NULL);
2981
2982 // There is no challenge info, since the identity worked.
2983 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2984
2985 EXPECT_EQ(100, response->headers->GetContentLength());
2986
2987 // Empty the current queue.
2988 MessageLoop::current()->RunAllPending();
2989}
2990
[email protected]f9ee6b52008-11-08 06:46:232991// Test that previously tried username/passwords for a realm get re-used.
2992TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592993 SessionDependencies session_deps;
2994 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232995
2996 // Transaction 1: authenticate (foo, bar) on MyRealm1
2997 {
[email protected]5695b8c2009-09-30 21:36:432998 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232999
[email protected]1c773ea12009-04-28 19:58:423000 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233001 request.method = "GET";
3002 request.url = GURL("http://www.google.com/x/y/z");
3003 request.load_flags = 0;
3004
3005 MockWrite data_writes1[] = {
3006 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3007 "Host: www.google.com\r\n"
3008 "Connection: keep-alive\r\n\r\n"),
3009 };
3010
3011 MockRead data_reads1[] = {
3012 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3013 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3014 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423015 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233016 };
3017
3018 // Resend with authorization (username=foo, password=bar)
3019 MockWrite data_writes2[] = {
3020 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3021 "Host: www.google.com\r\n"
3022 "Connection: keep-alive\r\n"
3023 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3024 };
3025
3026 // Sever accepts the authorization.
3027 MockRead data_reads2[] = {
3028 MockRead("HTTP/1.0 200 OK\r\n"),
3029 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423030 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233031 };
3032
[email protected]31a2bfe2010-02-09 08:03:393033 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3034 data_writes1, arraysize(data_writes1));
3035 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3036 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593037 session_deps.socket_factory.AddSocketDataProvider(&data1);
3038 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233039
3040 TestCompletionCallback callback1;
3041
[email protected]5a1d7ca2010-04-28 20:12:273042 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423043 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233044
3045 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423046 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233047
[email protected]1c773ea12009-04-28 19:58:423048 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233049 EXPECT_FALSE(response == NULL);
3050
3051 // The password prompt info should have been set in
3052 // response->auth_challenge.
3053 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3054
[email protected]71e4573a2009-05-21 22:03:003055 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233056 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3057 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3058
3059 TestCompletionCallback callback2;
3060
[email protected]13c8a092010-07-29 06:15:443061 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423062 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233063
3064 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423065 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233066
3067 response = trans->GetResponseInfo();
3068 EXPECT_FALSE(response == NULL);
3069 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3070 EXPECT_EQ(100, response->headers->GetContentLength());
3071 }
3072
3073 // ------------------------------------------------------------------------
3074
3075 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3076 {
[email protected]5695b8c2009-09-30 21:36:433077 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233078
[email protected]1c773ea12009-04-28 19:58:423079 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233080 request.method = "GET";
3081 // Note that Transaction 1 was at /x/y/z, so this is in the same
3082 // protection space as MyRealm1.
3083 request.url = GURL("http://www.google.com/x/y/a/b");
3084 request.load_flags = 0;
3085
3086 MockWrite data_writes1[] = {
3087 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3088 "Host: www.google.com\r\n"
3089 "Connection: keep-alive\r\n"
3090 // Send preemptive authorization for MyRealm1
3091 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3092 };
3093
3094 // The server didn't like the preemptive authorization, and
3095 // challenges us for a different realm (MyRealm2).
3096 MockRead data_reads1[] = {
3097 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3098 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3099 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423100 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233101 };
3102
3103 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3104 MockWrite data_writes2[] = {
3105 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3106 "Host: www.google.com\r\n"
3107 "Connection: keep-alive\r\n"
3108 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3109 };
3110
3111 // Sever accepts the authorization.
3112 MockRead data_reads2[] = {
3113 MockRead("HTTP/1.0 200 OK\r\n"),
3114 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423115 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233116 };
3117
[email protected]31a2bfe2010-02-09 08:03:393118 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3119 data_writes1, arraysize(data_writes1));
3120 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3121 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593122 session_deps.socket_factory.AddSocketDataProvider(&data1);
3123 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233124
3125 TestCompletionCallback callback1;
3126
[email protected]5a1d7ca2010-04-28 20:12:273127 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423128 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233129
3130 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423131 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233132
[email protected]1c773ea12009-04-28 19:58:423133 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233134 EXPECT_FALSE(response == NULL);
3135
3136 // The password prompt info should have been set in
3137 // response->auth_challenge.
3138 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3139
[email protected]71e4573a2009-05-21 22:03:003140 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233141 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3142 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3143
3144 TestCompletionCallback callback2;
3145
[email protected]13c8a092010-07-29 06:15:443146 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423147 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233148
3149 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423150 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233151
3152 response = trans->GetResponseInfo();
3153 EXPECT_FALSE(response == NULL);
3154 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3155 EXPECT_EQ(100, response->headers->GetContentLength());
3156 }
3157
3158 // ------------------------------------------------------------------------
3159
3160 // Transaction 3: Resend a request in MyRealm's protection space --
3161 // succeed with preemptive authorization.
3162 {
[email protected]5695b8c2009-09-30 21:36:433163 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233164
[email protected]1c773ea12009-04-28 19:58:423165 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233166 request.method = "GET";
3167 request.url = GURL("http://www.google.com/x/y/z2");
3168 request.load_flags = 0;
3169
3170 MockWrite data_writes1[] = {
3171 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3172 "Host: www.google.com\r\n"
3173 "Connection: keep-alive\r\n"
3174 // The authorization for MyRealm1 gets sent preemptively
3175 // (since the url is in the same protection space)
3176 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3177 };
3178
3179 // Sever accepts the preemptive authorization
3180 MockRead data_reads1[] = {
3181 MockRead("HTTP/1.0 200 OK\r\n"),
3182 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423183 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233184 };
3185
[email protected]31a2bfe2010-02-09 08:03:393186 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3187 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593188 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233189
3190 TestCompletionCallback callback1;
3191
[email protected]5a1d7ca2010-04-28 20:12:273192 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423193 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233194
3195 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423196 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233197
[email protected]1c773ea12009-04-28 19:58:423198 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233199 EXPECT_FALSE(response == NULL);
3200
3201 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3202 EXPECT_EQ(100, response->headers->GetContentLength());
3203 }
3204
3205 // ------------------------------------------------------------------------
3206
3207 // Transaction 4: request another URL in MyRealm (however the
3208 // url is not known to belong to the protection space, so no pre-auth).
3209 {
[email protected]5695b8c2009-09-30 21:36:433210 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233211
[email protected]1c773ea12009-04-28 19:58:423212 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233213 request.method = "GET";
3214 request.url = GURL("http://www.google.com/x/1");
3215 request.load_flags = 0;
3216
3217 MockWrite data_writes1[] = {
3218 MockWrite("GET /x/1 HTTP/1.1\r\n"
3219 "Host: www.google.com\r\n"
3220 "Connection: keep-alive\r\n\r\n"),
3221 };
3222
3223 MockRead data_reads1[] = {
3224 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3225 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3226 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423227 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233228 };
3229
3230 // Resend with authorization from MyRealm's cache.
3231 MockWrite data_writes2[] = {
3232 MockWrite("GET /x/1 HTTP/1.1\r\n"
3233 "Host: www.google.com\r\n"
3234 "Connection: keep-alive\r\n"
3235 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3236 };
3237
3238 // Sever accepts the authorization.
3239 MockRead data_reads2[] = {
3240 MockRead("HTTP/1.0 200 OK\r\n"),
3241 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423242 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233243 };
3244
[email protected]31a2bfe2010-02-09 08:03:393245 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3246 data_writes1, arraysize(data_writes1));
3247 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3248 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593249 session_deps.socket_factory.AddSocketDataProvider(&data1);
3250 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233251
3252 TestCompletionCallback callback1;
3253
[email protected]5a1d7ca2010-04-28 20:12:273254 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423255 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233256
3257 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423258 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233259
[email protected]0757e7702009-03-27 04:00:223260 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3261 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443262 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423263 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223264 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423265 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223266 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3267
[email protected]1c773ea12009-04-28 19:58:423268 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233269 EXPECT_FALSE(response == NULL);
3270 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3271 EXPECT_EQ(100, response->headers->GetContentLength());
3272 }
3273
3274 // ------------------------------------------------------------------------
3275
3276 // Transaction 5: request a URL in MyRealm, but the server rejects the
3277 // cached identity. Should invalidate and re-prompt.
3278 {
[email protected]5695b8c2009-09-30 21:36:433279 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233280
[email protected]1c773ea12009-04-28 19:58:423281 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233282 request.method = "GET";
3283 request.url = GURL("http://www.google.com/p/q/t");
3284 request.load_flags = 0;
3285
3286 MockWrite data_writes1[] = {
3287 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3288 "Host: www.google.com\r\n"
3289 "Connection: keep-alive\r\n\r\n"),
3290 };
3291
3292 MockRead data_reads1[] = {
3293 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3294 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3295 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423296 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233297 };
3298
3299 // Resend with authorization from cache for MyRealm.
3300 MockWrite data_writes2[] = {
3301 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3302 "Host: www.google.com\r\n"
3303 "Connection: keep-alive\r\n"
3304 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3305 };
3306
3307 // Sever rejects the authorization.
3308 MockRead data_reads2[] = {
3309 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3310 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3311 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423312 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233313 };
3314
3315 // At this point we should prompt for new credentials for MyRealm.
3316 // Restart with username=foo3, password=foo4.
3317 MockWrite data_writes3[] = {
3318 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3319 "Host: www.google.com\r\n"
3320 "Connection: keep-alive\r\n"
3321 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3322 };
3323
3324 // Sever accepts the authorization.
3325 MockRead data_reads3[] = {
3326 MockRead("HTTP/1.0 200 OK\r\n"),
3327 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423328 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233329 };
3330
[email protected]31a2bfe2010-02-09 08:03:393331 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3332 data_writes1, arraysize(data_writes1));
3333 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3334 data_writes2, arraysize(data_writes2));
3335 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3336 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593337 session_deps.socket_factory.AddSocketDataProvider(&data1);
3338 session_deps.socket_factory.AddSocketDataProvider(&data2);
3339 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233340
3341 TestCompletionCallback callback1;
3342
[email protected]5a1d7ca2010-04-28 20:12:273343 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423344 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233345
3346 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423347 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233348
[email protected]0757e7702009-03-27 04:00:223349 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3350 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443351 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423352 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223353 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423354 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223355 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3356
[email protected]1c773ea12009-04-28 19:58:423357 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233358 EXPECT_FALSE(response == NULL);
3359
3360 // The password prompt info should have been set in
3361 // response->auth_challenge.
3362 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3363
[email protected]71e4573a2009-05-21 22:03:003364 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233365 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3366 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3367
[email protected]0757e7702009-03-27 04:00:223368 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233369
[email protected]13c8a092010-07-29 06:15:443370 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423371 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233372
[email protected]0757e7702009-03-27 04:00:223373 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423374 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233375
3376 response = trans->GetResponseInfo();
3377 EXPECT_FALSE(response == NULL);
3378 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3379 EXPECT_EQ(100, response->headers->GetContentLength());
3380 }
3381}
[email protected]89ceba9a2009-03-21 03:46:063382
[email protected]3c32c5f2010-05-18 15:18:123383// Tests that nonce count increments when multiple auth attempts
3384// are started with the same nonce.
3385TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3386 SessionDependencies session_deps;
3387 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3388 HttpAuthHandlerDigest::SetFixedCnonce(true);
3389
3390 // Transaction 1: authenticate (foo, bar) on MyRealm1
3391 {
3392 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3393
3394 HttpRequestInfo request;
3395 request.method = "GET";
3396 request.url = GURL("http://www.google.com/x/y/z");
3397 request.load_flags = 0;
3398
3399 MockWrite data_writes1[] = {
3400 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3401 "Host: www.google.com\r\n"
3402 "Connection: keep-alive\r\n\r\n"),
3403 };
3404
3405 MockRead data_reads1[] = {
3406 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3407 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3408 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3409 MockRead(false, OK),
3410 };
3411
3412 // Resend with authorization (username=foo, password=bar)
3413 MockWrite data_writes2[] = {
3414 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3415 "Host: www.google.com\r\n"
3416 "Connection: keep-alive\r\n"
3417 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3418 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3419 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3420 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3421 };
3422
3423 // Sever accepts the authorization.
3424 MockRead data_reads2[] = {
3425 MockRead("HTTP/1.0 200 OK\r\n"),
3426 MockRead(false, OK),
3427 };
3428
3429 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3430 data_writes1, arraysize(data_writes1));
3431 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3432 data_writes2, arraysize(data_writes2));
3433 session_deps.socket_factory.AddSocketDataProvider(&data1);
3434 session_deps.socket_factory.AddSocketDataProvider(&data2);
3435
3436 TestCompletionCallback callback1;
3437
3438 int rv = trans->Start(&request, &callback1, BoundNetLog());
3439 EXPECT_EQ(ERR_IO_PENDING, rv);
3440
3441 rv = callback1.WaitForResult();
3442 EXPECT_EQ(OK, rv);
3443
3444 const HttpResponseInfo* response = trans->GetResponseInfo();
3445 ASSERT_FALSE(response == NULL);
3446
3447 // The password prompt info should have been set in
3448 // response->auth_challenge.
3449 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3450
3451 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3452 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3453 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3454
3455 TestCompletionCallback callback2;
3456
[email protected]13c8a092010-07-29 06:15:443457 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123458 EXPECT_EQ(ERR_IO_PENDING, rv);
3459
3460 rv = callback2.WaitForResult();
3461 EXPECT_EQ(OK, rv);
3462
3463 response = trans->GetResponseInfo();
3464 ASSERT_FALSE(response == NULL);
3465 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3466 }
3467
3468 // ------------------------------------------------------------------------
3469
3470 // Transaction 2: Request another resource in digestive's protection space.
3471 // This will preemptively add an Authorization header which should have an
3472 // "nc" value of 2 (as compared to 1 in the first use.
3473 {
3474 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3475
3476 HttpRequestInfo request;
3477 request.method = "GET";
3478 // Note that Transaction 1 was at /x/y/z, so this is in the same
3479 // protection space as digest.
3480 request.url = GURL("http://www.google.com/x/y/a/b");
3481 request.load_flags = 0;
3482
3483 MockWrite data_writes1[] = {
3484 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3485 "Host: www.google.com\r\n"
3486 "Connection: keep-alive\r\n"
3487 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3488 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3489 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3490 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3491 };
3492
3493 // Sever accepts the authorization.
3494 MockRead data_reads1[] = {
3495 MockRead("HTTP/1.0 200 OK\r\n"),
3496 MockRead("Content-Length: 100\r\n\r\n"),
3497 MockRead(false, OK),
3498 };
3499
3500 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3501 data_writes1, arraysize(data_writes1));
3502 session_deps.socket_factory.AddSocketDataProvider(&data1);
3503
3504 TestCompletionCallback callback1;
3505
3506 int rv = trans->Start(&request, &callback1, BoundNetLog());
3507 EXPECT_EQ(ERR_IO_PENDING, rv);
3508
3509 rv = callback1.WaitForResult();
3510 EXPECT_EQ(OK, rv);
3511
3512 const HttpResponseInfo* response = trans->GetResponseInfo();
3513 ASSERT_FALSE(response == NULL);
3514 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3515 }
3516}
3517
[email protected]89ceba9a2009-03-21 03:46:063518// Test the ResetStateForRestart() private method.
3519TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3520 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593521 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403522 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433523 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063524
3525 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063526 trans->read_buf_ = new IOBuffer(15);
3527 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573528 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063529
3530 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143531 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573532 response->auth_challenge = new AuthChallengeInfo();
3533 response->ssl_info.cert_status = -15;
3534 response->response_time = base::Time::Now();
3535 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063536
3537 { // Setup state for response_.vary_data
3538 HttpRequestInfo request;
3539 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3540 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573541 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433542 request.extra_headers.SetHeader("Foo", "1");
3543 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573544 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063545 }
3546
3547 // Cause the above state to be reset.
3548 trans->ResetStateForRestart();
3549
3550 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073551 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063552 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573553 EXPECT_EQ(0U, trans->request_headers_.size());
3554 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3555 EXPECT_TRUE(response->headers.get() == NULL);
3556 EXPECT_EQ(false, response->was_cached);
3557 EXPECT_EQ(0, response->ssl_info.cert_status);
3558 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063559}
3560
[email protected]bacff652009-03-31 17:50:333561// Test HTTPS connections to a site with a bad certificate
3562TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593563 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403564 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433565 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333566
3567 HttpRequestInfo request;
3568 request.method = "GET";
3569 request.url = GURL("https://www.google.com/");
3570 request.load_flags = 0;
3571
3572 MockWrite data_writes[] = {
3573 MockWrite("GET / HTTP/1.1\r\n"
3574 "Host: www.google.com\r\n"
3575 "Connection: keep-alive\r\n\r\n"),
3576 };
3577
3578 MockRead data_reads[] = {
3579 MockRead("HTTP/1.0 200 OK\r\n"),
3580 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3581 MockRead("Content-Length: 100\r\n\r\n"),
3582 MockRead(false, OK),
3583 };
3584
[email protected]5ecc992a42009-11-11 01:41:593585 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393586 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3587 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593588 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3589 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333590
[email protected]5ecc992a42009-11-11 01:41:593591 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3592 session_deps.socket_factory.AddSocketDataProvider(&data);
3593 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3594 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333595
3596 TestCompletionCallback callback;
3597
[email protected]5a1d7ca2010-04-28 20:12:273598 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333599 EXPECT_EQ(ERR_IO_PENDING, rv);
3600
3601 rv = callback.WaitForResult();
3602 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3603
3604 rv = trans->RestartIgnoringLastError(&callback);
3605 EXPECT_EQ(ERR_IO_PENDING, rv);
3606
3607 rv = callback.WaitForResult();
3608 EXPECT_EQ(OK, rv);
3609
3610 const HttpResponseInfo* response = trans->GetResponseInfo();
3611
3612 EXPECT_FALSE(response == NULL);
3613 EXPECT_EQ(100, response->headers->GetContentLength());
3614}
3615
3616// Test HTTPS connections to a site with a bad certificate, going through a
3617// proxy
3618TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593619 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333620
3621 HttpRequestInfo request;
3622 request.method = "GET";
3623 request.url = GURL("https://www.google.com/");
3624 request.load_flags = 0;
3625
3626 MockWrite proxy_writes[] = {
3627 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453628 "Host: www.google.com\r\n"
3629 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333630 };
3631
3632 MockRead proxy_reads[] = {
3633 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423634 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333635 };
3636
3637 MockWrite data_writes[] = {
3638 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453639 "Host: www.google.com\r\n"
3640 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333641 MockWrite("GET / HTTP/1.1\r\n"
3642 "Host: www.google.com\r\n"
3643 "Connection: keep-alive\r\n\r\n"),
3644 };
3645
3646 MockRead data_reads[] = {
3647 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3648 MockRead("HTTP/1.0 200 OK\r\n"),
3649 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3650 MockRead("Content-Length: 100\r\n\r\n"),
3651 MockRead(false, OK),
3652 };
3653
[email protected]31a2bfe2010-02-09 08:03:393654 StaticSocketDataProvider ssl_bad_certificate(
3655 proxy_reads, arraysize(proxy_reads),
3656 proxy_writes, arraysize(proxy_writes));
3657 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3658 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593659 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3660 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333661
[email protected]5ecc992a42009-11-11 01:41:593662 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3663 session_deps.socket_factory.AddSocketDataProvider(&data);
3664 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3665 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333666
3667 TestCompletionCallback callback;
3668
3669 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593670 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333671
[email protected]d207a5f2009-06-04 05:28:403672 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433673 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333674
[email protected]5a1d7ca2010-04-28 20:12:273675 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333676 EXPECT_EQ(ERR_IO_PENDING, rv);
3677
3678 rv = callback.WaitForResult();
3679 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3680
3681 rv = trans->RestartIgnoringLastError(&callback);
3682 EXPECT_EQ(ERR_IO_PENDING, rv);
3683
3684 rv = callback.WaitForResult();
3685 EXPECT_EQ(OK, rv);
3686
3687 const HttpResponseInfo* response = trans->GetResponseInfo();
3688
3689 EXPECT_FALSE(response == NULL);
3690 EXPECT_EQ(100, response->headers->GetContentLength());
3691 }
3692}
3693
[email protected]1c773ea12009-04-28 19:58:423694TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593695 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403696 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433697 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423698
3699 HttpRequestInfo request;
3700 request.method = "GET";
3701 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433702 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3703 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423704
3705 MockWrite data_writes[] = {
3706 MockWrite("GET / HTTP/1.1\r\n"
3707 "Host: www.google.com\r\n"
3708 "Connection: keep-alive\r\n"
3709 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3710 };
3711
3712 // Lastly, the server responds with the actual content.
3713 MockRead data_reads[] = {
3714 MockRead("HTTP/1.0 200 OK\r\n"),
3715 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3716 MockRead("Content-Length: 100\r\n\r\n"),
3717 MockRead(false, OK),
3718 };
3719
[email protected]31a2bfe2010-02-09 08:03:393720 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3721 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593722 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423723
3724 TestCompletionCallback callback;
3725
[email protected]5a1d7ca2010-04-28 20:12:273726 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423727 EXPECT_EQ(ERR_IO_PENDING, rv);
3728
3729 rv = callback.WaitForResult();
3730 EXPECT_EQ(OK, rv);
3731}
3732
[email protected]da81f132010-08-18 23:39:293733TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
3734 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3735 scoped_ptr<HttpTransaction> trans(
3736 new HttpNetworkTransaction(CreateSession(&session_deps)));
3737
3738 HttpRequestInfo request;
3739 request.method = "GET";
3740 request.url = GURL("https://www.google.com/");
3741 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3742 "Chromium Ultra Awesome X Edition");
3743
3744 MockWrite data_writes[] = {
3745 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3746 "Host: www.google.com\r\n"
3747 "Proxy-Connection: keep-alive\r\n"
3748 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3749 };
3750 MockRead data_reads[] = {
3751 // Return an error, so the transaction stops here (this test isn't
3752 // interested in the rest).
3753 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3754 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3755 MockRead("Proxy-Connection: close\r\n\r\n"),
3756 };
3757
3758 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3759 data_writes, arraysize(data_writes));
3760 session_deps.socket_factory.AddSocketDataProvider(&data);
3761
3762 TestCompletionCallback callback;
3763
3764 int rv = trans->Start(&request, &callback, BoundNetLog());
3765 EXPECT_EQ(ERR_IO_PENDING, rv);
3766
3767 rv = callback.WaitForResult();
3768 EXPECT_EQ(OK, rv);
3769}
3770
[email protected]1c773ea12009-04-28 19:58:423771TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593772 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403773 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433774 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423775
3776 HttpRequestInfo request;
3777 request.method = "GET";
3778 request.url = GURL("http://www.google.com/");
3779 request.load_flags = 0;
3780 request.referrer = GURL("http://the.previous.site.com/");
3781
3782 MockWrite data_writes[] = {
3783 MockWrite("GET / HTTP/1.1\r\n"
3784 "Host: www.google.com\r\n"
3785 "Connection: keep-alive\r\n"
3786 "Referer: http://the.previous.site.com/\r\n\r\n"),
3787 };
3788
3789 // Lastly, the server responds with the actual content.
3790 MockRead data_reads[] = {
3791 MockRead("HTTP/1.0 200 OK\r\n"),
3792 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3793 MockRead("Content-Length: 100\r\n\r\n"),
3794 MockRead(false, OK),
3795 };
3796
[email protected]31a2bfe2010-02-09 08:03:393797 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3798 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593799 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423800
3801 TestCompletionCallback callback;
3802
[email protected]5a1d7ca2010-04-28 20:12:273803 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423804 EXPECT_EQ(ERR_IO_PENDING, rv);
3805
3806 rv = callback.WaitForResult();
3807 EXPECT_EQ(OK, rv);
3808}
3809
3810TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593811 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403812 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433813 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423814
3815 HttpRequestInfo request;
3816 request.method = "POST";
3817 request.url = GURL("http://www.google.com/");
3818
3819 MockWrite data_writes[] = {
3820 MockWrite("POST / HTTP/1.1\r\n"
3821 "Host: www.google.com\r\n"
3822 "Connection: keep-alive\r\n"
3823 "Content-Length: 0\r\n\r\n"),
3824 };
3825
3826 // Lastly, the server responds with the actual content.
3827 MockRead data_reads[] = {
3828 MockRead("HTTP/1.0 200 OK\r\n"),
3829 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3830 MockRead("Content-Length: 100\r\n\r\n"),
3831 MockRead(false, OK),
3832 };
3833
[email protected]31a2bfe2010-02-09 08:03:393834 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3835 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593836 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423837
3838 TestCompletionCallback callback;
3839
[email protected]5a1d7ca2010-04-28 20:12:273840 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423841 EXPECT_EQ(ERR_IO_PENDING, rv);
3842
3843 rv = callback.WaitForResult();
3844 EXPECT_EQ(OK, rv);
3845}
3846
3847TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593848 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403849 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433850 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423851
3852 HttpRequestInfo request;
3853 request.method = "PUT";
3854 request.url = GURL("http://www.google.com/");
3855
3856 MockWrite data_writes[] = {
3857 MockWrite("PUT / HTTP/1.1\r\n"
3858 "Host: www.google.com\r\n"
3859 "Connection: keep-alive\r\n"
3860 "Content-Length: 0\r\n\r\n"),
3861 };
3862
3863 // Lastly, the server responds with the actual content.
3864 MockRead data_reads[] = {
3865 MockRead("HTTP/1.0 200 OK\r\n"),
3866 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3867 MockRead("Content-Length: 100\r\n\r\n"),
3868 MockRead(false, OK),
3869 };
3870
[email protected]31a2bfe2010-02-09 08:03:393871 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3872 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593873 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423874
3875 TestCompletionCallback callback;
3876
[email protected]5a1d7ca2010-04-28 20:12:273877 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423878 EXPECT_EQ(ERR_IO_PENDING, rv);
3879
3880 rv = callback.WaitForResult();
3881 EXPECT_EQ(OK, rv);
3882}
3883
3884TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593885 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403886 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433887 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423888
3889 HttpRequestInfo request;
3890 request.method = "HEAD";
3891 request.url = GURL("http://www.google.com/");
3892
3893 MockWrite data_writes[] = {
3894 MockWrite("HEAD / HTTP/1.1\r\n"
3895 "Host: www.google.com\r\n"
3896 "Connection: keep-alive\r\n"
3897 "Content-Length: 0\r\n\r\n"),
3898 };
3899
3900 // Lastly, the server responds with the actual content.
3901 MockRead data_reads[] = {
3902 MockRead("HTTP/1.0 200 OK\r\n"),
3903 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3904 MockRead("Content-Length: 100\r\n\r\n"),
3905 MockRead(false, OK),
3906 };
3907
[email protected]31a2bfe2010-02-09 08:03:393908 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3909 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593910 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423911
3912 TestCompletionCallback callback;
3913
[email protected]5a1d7ca2010-04-28 20:12:273914 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423915 EXPECT_EQ(ERR_IO_PENDING, rv);
3916
3917 rv = callback.WaitForResult();
3918 EXPECT_EQ(OK, rv);
3919}
3920
3921TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593922 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403923 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433924 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423925
3926 HttpRequestInfo request;
3927 request.method = "GET";
3928 request.url = GURL("http://www.google.com/");
3929 request.load_flags = LOAD_BYPASS_CACHE;
3930
3931 MockWrite data_writes[] = {
3932 MockWrite("GET / HTTP/1.1\r\n"
3933 "Host: www.google.com\r\n"
3934 "Connection: keep-alive\r\n"
3935 "Pragma: no-cache\r\n"
3936 "Cache-Control: no-cache\r\n\r\n"),
3937 };
3938
3939 // Lastly, the server responds with the actual content.
3940 MockRead data_reads[] = {
3941 MockRead("HTTP/1.0 200 OK\r\n"),
3942 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3943 MockRead("Content-Length: 100\r\n\r\n"),
3944 MockRead(false, OK),
3945 };
3946
[email protected]31a2bfe2010-02-09 08:03:393947 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3948 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593949 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423950
3951 TestCompletionCallback callback;
3952
[email protected]5a1d7ca2010-04-28 20:12:273953 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423954 EXPECT_EQ(ERR_IO_PENDING, rv);
3955
3956 rv = callback.WaitForResult();
3957 EXPECT_EQ(OK, rv);
3958}
3959
3960TEST_F(HttpNetworkTransactionTest,
3961 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593962 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403963 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433964 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423965
3966 HttpRequestInfo request;
3967 request.method = "GET";
3968 request.url = GURL("http://www.google.com/");
3969 request.load_flags = LOAD_VALIDATE_CACHE;
3970
3971 MockWrite data_writes[] = {
3972 MockWrite("GET / HTTP/1.1\r\n"
3973 "Host: www.google.com\r\n"
3974 "Connection: keep-alive\r\n"
3975 "Cache-Control: max-age=0\r\n\r\n"),
3976 };
3977
3978 // Lastly, the server responds with the actual content.
3979 MockRead data_reads[] = {
3980 MockRead("HTTP/1.0 200 OK\r\n"),
3981 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3982 MockRead("Content-Length: 100\r\n\r\n"),
3983 MockRead(false, OK),
3984 };
3985
[email protected]31a2bfe2010-02-09 08:03:393986 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3987 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593988 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423989
3990 TestCompletionCallback callback;
3991
[email protected]5a1d7ca2010-04-28 20:12:273992 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423993 EXPECT_EQ(ERR_IO_PENDING, rv);
3994
3995 rv = callback.WaitForResult();
3996 EXPECT_EQ(OK, rv);
3997}
3998
3999TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594000 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404001 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434002 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424003
4004 HttpRequestInfo request;
4005 request.method = "GET";
4006 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434007 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424008
4009 MockWrite data_writes[] = {
4010 MockWrite("GET / HTTP/1.1\r\n"
4011 "Host: www.google.com\r\n"
4012 "Connection: keep-alive\r\n"
4013 "FooHeader: Bar\r\n\r\n"),
4014 };
4015
4016 // Lastly, the server responds with the actual content.
4017 MockRead data_reads[] = {
4018 MockRead("HTTP/1.0 200 OK\r\n"),
4019 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4020 MockRead("Content-Length: 100\r\n\r\n"),
4021 MockRead(false, OK),
4022 };
4023
[email protected]31a2bfe2010-02-09 08:03:394024 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4025 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594026 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424027
4028 TestCompletionCallback callback;
4029
[email protected]5a1d7ca2010-04-28 20:12:274030 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424031 EXPECT_EQ(ERR_IO_PENDING, rv);
4032
4033 rv = callback.WaitForResult();
4034 EXPECT_EQ(OK, rv);
4035}
4036
[email protected]270c6412010-03-29 22:02:474037TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4038 SessionDependencies session_deps;
4039 scoped_ptr<HttpTransaction> trans(
4040 new HttpNetworkTransaction(CreateSession(&session_deps)));
4041
4042 HttpRequestInfo request;
4043 request.method = "GET";
4044 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434045 request.extra_headers.SetHeader("referer", "www.foo.com");
4046 request.extra_headers.SetHeader("hEllo", "Kitty");
4047 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474048
4049 MockWrite data_writes[] = {
4050 MockWrite("GET / HTTP/1.1\r\n"
4051 "Host: www.google.com\r\n"
4052 "Connection: keep-alive\r\n"
4053 "hEllo: Kitty\r\n"
4054 "FoO: bar\r\n\r\n"),
4055 };
4056
4057 // Lastly, the server responds with the actual content.
4058 MockRead data_reads[] = {
4059 MockRead("HTTP/1.0 200 OK\r\n"),
4060 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4061 MockRead("Content-Length: 100\r\n\r\n"),
4062 MockRead(false, OK),
4063 };
4064
4065 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4066 data_writes, arraysize(data_writes));
4067 session_deps.socket_factory.AddSocketDataProvider(&data);
4068
4069 TestCompletionCallback callback;
4070
[email protected]5a1d7ca2010-04-28 20:12:274071 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474072 EXPECT_EQ(ERR_IO_PENDING, rv);
4073
4074 rv = callback.WaitForResult();
4075 EXPECT_EQ(OK, rv);
4076}
4077
[email protected]3cd17242009-06-23 02:59:024078TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094079 SessionDependencies session_deps(
4080 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024081
4082 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434083 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024084
4085 HttpRequestInfo request;
4086 request.method = "GET";
4087 request.url = GURL("http://www.google.com/");
4088 request.load_flags = 0;
4089
4090 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4091 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4092
4093 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354094 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024095 MockWrite("GET / HTTP/1.1\r\n"
4096 "Host: www.google.com\r\n"
4097 "Connection: keep-alive\r\n\r\n")
4098 };
4099
4100 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594101 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024102 MockRead("HTTP/1.0 200 OK\r\n"),
4103 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4104 MockRead("Payload"),
4105 MockRead(false, OK)
4106 };
4107
[email protected]31a2bfe2010-02-09 08:03:394108 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4109 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594110 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024111
4112 TestCompletionCallback callback;
4113
[email protected]5a1d7ca2010-04-28 20:12:274114 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024115 EXPECT_EQ(ERR_IO_PENDING, rv);
4116
4117 rv = callback.WaitForResult();
4118 EXPECT_EQ(OK, rv);
4119
4120 const HttpResponseInfo* response = trans->GetResponseInfo();
4121 EXPECT_FALSE(response == NULL);
4122
4123 std::string response_text;
4124 rv = ReadTransaction(trans.get(), &response_text);
4125 EXPECT_EQ(OK, rv);
4126 EXPECT_EQ("Payload", response_text);
4127}
4128
4129TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094130 SessionDependencies session_deps(
4131 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024132
4133 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434134 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024135
4136 HttpRequestInfo request;
4137 request.method = "GET";
4138 request.url = GURL("https://www.google.com/");
4139 request.load_flags = 0;
4140
4141 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4142 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4143
4144 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354145 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4146 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024147 MockWrite("GET / HTTP/1.1\r\n"
4148 "Host: www.google.com\r\n"
4149 "Connection: keep-alive\r\n\r\n")
4150 };
4151
4152 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354153 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4154 arraysize(read_buffer)),
4155 MockRead("HTTP/1.0 200 OK\r\n"),
4156 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4157 MockRead("Payload"),
4158 MockRead(false, OK)
4159 };
4160
[email protected]31a2bfe2010-02-09 08:03:394161 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4162 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594163 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354164
[email protected]5ecc992a42009-11-11 01:41:594165 SSLSocketDataProvider ssl(true, OK);
4166 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354167
4168 TestCompletionCallback callback;
4169
[email protected]5a1d7ca2010-04-28 20:12:274170 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354171 EXPECT_EQ(ERR_IO_PENDING, rv);
4172
4173 rv = callback.WaitForResult();
4174 EXPECT_EQ(OK, rv);
4175
4176 const HttpResponseInfo* response = trans->GetResponseInfo();
4177 EXPECT_FALSE(response == NULL);
4178
4179 std::string response_text;
4180 rv = ReadTransaction(trans.get(), &response_text);
4181 EXPECT_EQ(OK, rv);
4182 EXPECT_EQ("Payload", response_text);
4183}
4184
4185TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094186 SessionDependencies session_deps(
4187 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354188
4189 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434190 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354191
4192 HttpRequestInfo request;
4193 request.method = "GET";
4194 request.url = GURL("http://www.google.com/");
4195 request.load_flags = 0;
4196
4197 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4198 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374199 const char kSOCKS5OkRequest[] = {
4200 0x05, // Version
4201 0x01, // Command (CONNECT)
4202 0x00, // Reserved.
4203 0x03, // Address type (DOMAINNAME).
4204 0x0E, // Length of domain (14)
4205 // Domain string:
4206 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4207 0x00, 0x50, // 16-bit port (80)
4208 };
[email protected]e0c27be2009-07-15 13:09:354209 const char kSOCKS5OkResponse[] =
4210 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4211
4212 MockWrite data_writes[] = {
4213 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4214 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4215 MockWrite("GET / HTTP/1.1\r\n"
4216 "Host: www.google.com\r\n"
4217 "Connection: keep-alive\r\n\r\n")
4218 };
4219
4220 MockRead data_reads[] = {
4221 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4222 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4223 MockRead("HTTP/1.0 200 OK\r\n"),
4224 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4225 MockRead("Payload"),
4226 MockRead(false, OK)
4227 };
4228
[email protected]31a2bfe2010-02-09 08:03:394229 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4230 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594231 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354232
4233 TestCompletionCallback callback;
4234
[email protected]5a1d7ca2010-04-28 20:12:274235 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354236 EXPECT_EQ(ERR_IO_PENDING, rv);
4237
4238 rv = callback.WaitForResult();
4239 EXPECT_EQ(OK, rv);
4240
4241 const HttpResponseInfo* response = trans->GetResponseInfo();
4242 EXPECT_FALSE(response == NULL);
4243
4244 std::string response_text;
4245 rv = ReadTransaction(trans.get(), &response_text);
4246 EXPECT_EQ(OK, rv);
4247 EXPECT_EQ("Payload", response_text);
4248}
4249
4250TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094251 SessionDependencies session_deps(
4252 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354253
4254 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434255 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354256
4257 HttpRequestInfo request;
4258 request.method = "GET";
4259 request.url = GURL("https://www.google.com/");
4260 request.load_flags = 0;
4261
4262 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4263 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374264 const unsigned char kSOCKS5OkRequest[] = {
4265 0x05, // Version
4266 0x01, // Command (CONNECT)
4267 0x00, // Reserved.
4268 0x03, // Address type (DOMAINNAME).
4269 0x0E, // Length of domain (14)
4270 // Domain string:
4271 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4272 0x01, 0xBB, // 16-bit port (443)
4273 };
4274
[email protected]e0c27be2009-07-15 13:09:354275 const char kSOCKS5OkResponse[] =
4276 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4277
4278 MockWrite data_writes[] = {
4279 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4280 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4281 arraysize(kSOCKS5OkRequest)),
4282 MockWrite("GET / HTTP/1.1\r\n"
4283 "Host: www.google.com\r\n"
4284 "Connection: keep-alive\r\n\r\n")
4285 };
4286
4287 MockRead data_reads[] = {
4288 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4289 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024290 MockRead("HTTP/1.0 200 OK\r\n"),
4291 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4292 MockRead("Payload"),
4293 MockRead(false, OK)
4294 };
4295
[email protected]31a2bfe2010-02-09 08:03:394296 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4297 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594298 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024299
[email protected]5ecc992a42009-11-11 01:41:594300 SSLSocketDataProvider ssl(true, OK);
4301 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024302
4303 TestCompletionCallback callback;
4304
[email protected]5a1d7ca2010-04-28 20:12:274305 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024306 EXPECT_EQ(ERR_IO_PENDING, rv);
4307
4308 rv = callback.WaitForResult();
4309 EXPECT_EQ(OK, rv);
4310
4311 const HttpResponseInfo* response = trans->GetResponseInfo();
4312 EXPECT_FALSE(response == NULL);
4313
4314 std::string response_text;
4315 rv = ReadTransaction(trans.get(), &response_text);
4316 EXPECT_EQ(OK, rv);
4317 EXPECT_EQ("Payload", response_text);
4318}
4319
[email protected]04e5be32009-06-26 20:00:314320// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064321
4322struct GroupNameTest {
4323 std::string proxy_server;
4324 std::string url;
4325 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184326 bool ssl;
[email protected]2d731a32010-04-29 01:04:064327};
4328
4329scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4330 const std::string& proxy_server) {
4331 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4333
4334 HttpAlternateProtocols* alternate_protocols =
4335 session->mutable_alternate_protocols();
4336 alternate_protocols->SetAlternateProtocolFor(
4337 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354338 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064339
4340 return session;
4341}
4342
4343int GroupNameTransactionHelper(
4344 const std::string& url,
4345 const scoped_refptr<HttpNetworkSession>& session) {
4346 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4347
4348 HttpRequestInfo request;
4349 request.method = "GET";
4350 request.url = GURL(url);
4351 request.load_flags = 0;
4352
4353 TestCompletionCallback callback;
4354
4355 // We do not complete this request, the dtor will clean the transaction up.
4356 return trans->Start(&request, &callback, BoundNetLog());
4357}
4358
4359TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4360 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314361 {
[email protected]2d731a32010-04-29 01:04:064362 "", // unused
[email protected]04e5be32009-06-26 20:00:314363 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544364 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184365 false,
[email protected]2ff8b312010-04-26 22:20:544366 },
4367 {
[email protected]2d731a32010-04-29 01:04:064368 "", // unused
[email protected]2ff8b312010-04-26 22:20:544369 "http://[2001:1418:13:1::25]/direct",
4370 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184371 false,
[email protected]04e5be32009-06-26 20:00:314372 },
[email protected]04e5be32009-06-26 20:00:314373
4374 // SSL Tests
4375 {
[email protected]2d731a32010-04-29 01:04:064376 "", // unused
[email protected]04e5be32009-06-26 20:00:314377 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024378 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184379 true,
[email protected]04e5be32009-06-26 20:00:314380 },
4381 {
[email protected]2d731a32010-04-29 01:04:064382 "", // unused
4383 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024384 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184385 true,
[email protected]04e5be32009-06-26 20:00:314386 },
4387 {
[email protected]2d731a32010-04-29 01:04:064388 "", // unused
[email protected]2ff8b312010-04-26 22:20:544389 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024390 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184391 true,
[email protected]2ff8b312010-04-26 22:20:544392 },
[email protected]2d731a32010-04-29 01:04:064393 };
[email protected]2ff8b312010-04-26 22:20:544394
[email protected]8e6441ca2010-08-19 05:56:384395 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064396
4397 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4398 scoped_refptr<HttpNetworkSession> session(
4399 SetupSessionForGroupNameTests(tests[i].proxy_server));
4400
4401 HttpNetworkSessionPeer peer(session);
4402 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4403 new CaptureGroupNameTCPSocketPool(session.get()));
4404 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184405 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4406 new CaptureGroupNameSSLSocketPool(session.get()));
4407 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064408
4409 EXPECT_EQ(ERR_IO_PENDING,
4410 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184411 if (tests[i].ssl)
4412 EXPECT_EQ(tests[i].expected_group_name,
4413 ssl_conn_pool->last_group_name_received());
4414 else
4415 EXPECT_EQ(tests[i].expected_group_name,
4416 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064417 }
4418
[email protected]8e6441ca2010-08-19 05:56:384419 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064420}
4421
4422TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4423 const GroupNameTest tests[] = {
4424 {
4425 "http_proxy",
4426 "http://www.google.com/http_proxy_normal",
4427 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184428 false,
[email protected]2d731a32010-04-29 01:04:064429 },
4430
4431 // SSL Tests
4432 {
4433 "http_proxy",
4434 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024435 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184436 true,
[email protected]2d731a32010-04-29 01:04:064437 },
4438
[email protected]9faeded92010-04-29 20:03:054439 {
4440 "http_proxy",
4441 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024442 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184443 true,
[email protected]9faeded92010-04-29 20:03:054444 },
[email protected]2d731a32010-04-29 01:04:064445 };
4446
[email protected]8e6441ca2010-08-19 05:56:384447 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064448
4449 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4450 scoped_refptr<HttpNetworkSession> session(
4451 SetupSessionForGroupNameTests(tests[i].proxy_server));
4452
4453 HttpNetworkSessionPeer peer(session);
4454
[email protected]e60e47a2010-07-14 03:37:184455 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134456 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4457 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184458 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4459 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4460 new CaptureGroupNameSSLSocketPool(session.get()));
4461 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064462
4463 EXPECT_EQ(ERR_IO_PENDING,
4464 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184465 if (tests[i].ssl)
4466 EXPECT_EQ(tests[i].expected_group_name,
4467 ssl_conn_pool->last_group_name_received());
4468 else
4469 EXPECT_EQ(tests[i].expected_group_name,
4470 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064471 }
4472
[email protected]8e6441ca2010-08-19 05:56:384473 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064474}
4475
4476TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4477 const GroupNameTest tests[] = {
4478 {
4479 "socks4://socks_proxy:1080",
4480 "http://www.google.com/socks4_direct",
4481 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184482 false,
[email protected]2d731a32010-04-29 01:04:064483 },
4484 {
4485 "socks5://socks_proxy:1080",
4486 "http://www.google.com/socks5_direct",
4487 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184488 false,
[email protected]2d731a32010-04-29 01:04:064489 },
4490
4491 // SSL Tests
4492 {
4493 "socks4://socks_proxy:1080",
4494 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024495 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184496 true,
[email protected]2d731a32010-04-29 01:04:064497 },
4498 {
4499 "socks5://socks_proxy:1080",
4500 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024501 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184502 true,
[email protected]2d731a32010-04-29 01:04:064503 },
4504
[email protected]9faeded92010-04-29 20:03:054505 {
4506 "socks4://socks_proxy:1080",
4507 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024508 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184509 true,
[email protected]9faeded92010-04-29 20:03:054510 },
[email protected]04e5be32009-06-26 20:00:314511 };
4512
[email protected]8e6441ca2010-08-19 05:56:384513 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:544514
[email protected]04e5be32009-06-26 20:00:314515 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064516 scoped_refptr<HttpNetworkSession> session(
4517 SetupSessionForGroupNameTests(tests[i].proxy_server));
4518 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314519
[email protected]e60e47a2010-07-14 03:37:184520 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264521 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064522 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184523 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4524 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4525 new CaptureGroupNameSSLSocketPool(session.get()));
4526 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314527
[email protected]5695b8c2009-09-30 21:36:434528 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314529
[email protected]2d731a32010-04-29 01:04:064530 EXPECT_EQ(ERR_IO_PENDING,
4531 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184532 if (tests[i].ssl)
4533 EXPECT_EQ(tests[i].expected_group_name,
4534 ssl_conn_pool->last_group_name_received());
4535 else
4536 EXPECT_EQ(tests[i].expected_group_name,
4537 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314538 }
[email protected]2ff8b312010-04-26 22:20:544539
[email protected]8e6441ca2010-08-19 05:56:384540 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:314541}
4542
[email protected]9172a982009-06-06 00:30:254543TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544544 SessionDependencies session_deps(
4545 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324546
[email protected]69719062010-01-05 20:09:214547 // This simulates failure resolving all hostnames; that means we will fail
4548 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324549 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4550
[email protected]9172a982009-06-06 00:30:254551 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434552 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254553
4554 HttpRequestInfo request;
4555 request.method = "GET";
4556 request.url = GURL("http://www.google.com/");
4557
4558 TestCompletionCallback callback;
4559
[email protected]5a1d7ca2010-04-28 20:12:274560 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254561 EXPECT_EQ(ERR_IO_PENDING, rv);
4562
[email protected]9172a982009-06-06 00:30:254563 rv = callback.WaitForResult();
4564 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4565}
4566
[email protected]f3e6c1e2009-06-15 20:52:124567// Host resolution observer used by
4568// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4569// resovle requests are issued with a referrer of |expected_referrer|.
4570class ResolutionReferrerObserver : public HostResolver::Observer {
4571 public:
4572 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4573 : expected_referrer_(expected_referrer),
4574 called_start_with_referrer_(false),
4575 called_finish_with_referrer_(false) {
4576 }
4577
4578 virtual void OnStartResolution(int id,
4579 const HostResolver::RequestInfo& info) {
4580 if (info.referrer() == expected_referrer_)
4581 called_start_with_referrer_ = true;
4582 }
4583
4584 virtual void OnFinishResolutionWithStatus(
4585 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4586 if (info.referrer() == expected_referrer_)
4587 called_finish_with_referrer_ = true;
4588 }
4589
[email protected]eb255d32009-06-17 02:11:034590 virtual void OnCancelResolution(int id,
4591 const HostResolver::RequestInfo& info ) {
4592 FAIL() << "Should not be cancelling any requests!";
4593 }
4594
[email protected]f3e6c1e2009-06-15 20:52:124595 bool did_complete_with_expected_referrer() const {
4596 return called_start_with_referrer_ && called_finish_with_referrer_;
4597 }
4598
4599 private:
4600 GURL expected_referrer_;
4601 bool called_start_with_referrer_;
4602 bool called_finish_with_referrer_;
4603
4604 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4605};
4606
4607// Make sure that when HostResolver::Resolve() is invoked, it passes through
4608// the "referrer". This is depended on by the DNS prefetch observer.
4609TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4610 GURL referrer = GURL("http://expected-referrer/");
4611 EXPECT_TRUE(referrer.is_valid());
4612 ResolutionReferrerObserver resolution_observer(referrer);
4613
4614 SessionDependencies session_deps;
4615 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434616 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124617
4618 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144619 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124620
4621 // Connect up a mock socket which will fail when reading.
4622 MockRead data_reads[] = {
4623 MockRead(false, ERR_FAILED),
4624 };
[email protected]31a2bfe2010-02-09 08:03:394625 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594626 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124627
4628 // Issue a request, containing an HTTP referrer.
4629 HttpRequestInfo request;
4630 request.method = "GET";
4631 request.referrer = referrer;
4632 request.url = GURL("http://www.google.com/");
4633
4634 // Run the request until it fails reading from the socket.
4635 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274636 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124637 EXPECT_EQ(ERR_IO_PENDING, rv);
4638 rv = callback.WaitForResult();
4639 EXPECT_EQ(ERR_FAILED, rv);
4640
4641 // Check that the host resolution observer saw |referrer|.
4642 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4643}
4644
[email protected]685af592010-05-11 19:31:244645// Base test to make sure that when the load flags for a request specify to
4646// bypass the cache, the DNS cache is not used.
4647void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284648 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324649
[email protected]a2c2fb92009-07-18 07:31:044650 // Select a host resolver that does caching.
4651 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324652
[email protected]3b9cca42009-06-16 01:08:284653 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434654 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284655
4656 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4657 // a synchronous lookup.)
4658 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144659 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464660 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274661 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284662 EXPECT_EQ(OK, rv);
4663
4664 // Verify that it was added to host cache, by doing a subsequent async lookup
4665 // and confirming it completes synchronously.
4666 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464667 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284668 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274669 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324670 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284671
4672 // Inject a failure the next time that "www.google.com" is resolved. This way
4673 // we can tell if the next lookup hit the cache, or the "network".
4674 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324675 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284676
4677 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4678 // first read -- this won't be reached as the host resolution will fail first.
4679 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394680 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594681 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284682
4683 // Issue a request, asking to bypass the cache(s).
4684 HttpRequestInfo request;
4685 request.method = "GET";
[email protected]685af592010-05-11 19:31:244686 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284687 request.url = GURL("http://www.google.com/");
4688
4689 // Run the request.
4690 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274691 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284692 ASSERT_EQ(ERR_IO_PENDING, rv);
4693 rv = callback.WaitForResult();
4694
4695 // If we bypassed the cache, we would have gotten a failure while resolving
4696 // "www.google.com".
4697 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4698}
4699
[email protected]685af592010-05-11 19:31:244700// There are multiple load flags that should trigger the host cache bypass.
4701// Test each in isolation:
4702TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4703 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4704}
4705
4706TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4707 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4708}
4709
4710TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4711 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4712}
4713
[email protected]0877e3d2009-10-17 22:29:574714// Make sure we can handle an error when writing the request.
4715TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4716 SessionDependencies session_deps;
4717 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4718
4719 HttpRequestInfo request;
4720 request.method = "GET";
4721 request.url = GURL("http://www.foo.com/");
4722 request.load_flags = 0;
4723
4724 MockWrite write_failure[] = {
4725 MockWrite(true, ERR_CONNECTION_RESET),
4726 };
[email protected]31a2bfe2010-02-09 08:03:394727 StaticSocketDataProvider data(NULL, 0,
4728 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594729 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574730
4731 TestCompletionCallback callback;
4732
4733 scoped_ptr<HttpTransaction> trans(
4734 new HttpNetworkTransaction(CreateSession(&session_deps)));
4735
[email protected]5a1d7ca2010-04-28 20:12:274736 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574737 EXPECT_EQ(ERR_IO_PENDING, rv);
4738
4739 rv = callback.WaitForResult();
4740 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4741}
4742
4743// Check that a connection closed after the start of the headers finishes ok.
4744TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4745 SessionDependencies session_deps;
4746 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4747
4748 HttpRequestInfo request;
4749 request.method = "GET";
4750 request.url = GURL("http://www.foo.com/");
4751 request.load_flags = 0;
4752
4753 MockRead data_reads[] = {
4754 MockRead("HTTP/1."),
4755 MockRead(false, OK),
4756 };
4757
[email protected]31a2bfe2010-02-09 08:03:394758 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594759 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574760
4761 TestCompletionCallback callback;
4762
4763 scoped_ptr<HttpTransaction> trans(
4764 new HttpNetworkTransaction(CreateSession(&session_deps)));
4765
[email protected]5a1d7ca2010-04-28 20:12:274766 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574767 EXPECT_EQ(ERR_IO_PENDING, rv);
4768
4769 rv = callback.WaitForResult();
4770 EXPECT_EQ(OK, rv);
4771
4772 const HttpResponseInfo* response = trans->GetResponseInfo();
4773 EXPECT_TRUE(response != NULL);
4774
4775 EXPECT_TRUE(response->headers != NULL);
4776 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4777
4778 std::string response_data;
4779 rv = ReadTransaction(trans.get(), &response_data);
4780 EXPECT_EQ(OK, rv);
4781 EXPECT_EQ("", response_data);
4782}
4783
4784// Make sure that a dropped connection while draining the body for auth
4785// restart does the right thing.
4786TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4787 SessionDependencies session_deps;
4788 scoped_ptr<HttpTransaction> trans(
4789 new HttpNetworkTransaction(CreateSession(&session_deps)));
4790
4791 HttpRequestInfo request;
4792 request.method = "GET";
4793 request.url = GURL("http://www.google.com/");
4794 request.load_flags = 0;
4795
4796 MockWrite data_writes1[] = {
4797 MockWrite("GET / HTTP/1.1\r\n"
4798 "Host: www.google.com\r\n"
4799 "Connection: keep-alive\r\n\r\n"),
4800 };
4801
4802 MockRead data_reads1[] = {
4803 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4804 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4805 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4806 MockRead("Content-Length: 14\r\n\r\n"),
4807 MockRead("Unauth"),
4808 MockRead(true, ERR_CONNECTION_RESET),
4809 };
4810
[email protected]31a2bfe2010-02-09 08:03:394811 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4812 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594813 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574814
4815 // After calling trans->RestartWithAuth(), this is the request we should
4816 // be issuing -- the final header line contains the credentials.
4817 MockWrite data_writes2[] = {
4818 MockWrite("GET / HTTP/1.1\r\n"
4819 "Host: www.google.com\r\n"
4820 "Connection: keep-alive\r\n"
4821 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4822 };
4823
4824 // Lastly, the server responds with the actual content.
4825 MockRead data_reads2[] = {
4826 MockRead("HTTP/1.1 200 OK\r\n"),
4827 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4828 MockRead("Content-Length: 100\r\n\r\n"),
4829 MockRead(false, OK),
4830 };
4831
[email protected]31a2bfe2010-02-09 08:03:394832 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4833 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594834 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574835
4836 TestCompletionCallback callback1;
4837
[email protected]5a1d7ca2010-04-28 20:12:274838 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574839 EXPECT_EQ(ERR_IO_PENDING, rv);
4840
4841 rv = callback1.WaitForResult();
4842 EXPECT_EQ(OK, rv);
4843
4844 const HttpResponseInfo* response = trans->GetResponseInfo();
4845 EXPECT_FALSE(response == NULL);
4846
4847 // The password prompt info should have been set in response->auth_challenge.
4848 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4849
4850 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4851 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4852 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4853
4854 TestCompletionCallback callback2;
4855
[email protected]13c8a092010-07-29 06:15:444856 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:574857 EXPECT_EQ(ERR_IO_PENDING, rv);
4858
4859 rv = callback2.WaitForResult();
4860 EXPECT_EQ(OK, rv);
4861
4862 response = trans->GetResponseInfo();
4863 EXPECT_FALSE(response == NULL);
4864 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4865 EXPECT_EQ(100, response->headers->GetContentLength());
4866}
4867
4868// Test HTTPS connections going through a proxy that sends extra data.
4869TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4870 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4871
4872 HttpRequestInfo request;
4873 request.method = "GET";
4874 request.url = GURL("https://www.google.com/");
4875 request.load_flags = 0;
4876
4877 MockRead proxy_reads[] = {
4878 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4879 MockRead(false, OK)
4880 };
4881
[email protected]31a2bfe2010-02-09 08:03:394882 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594883 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574884
[email protected]5ecc992a42009-11-11 01:41:594885 session_deps.socket_factory.AddSocketDataProvider(&data);
4886 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574887
4888 TestCompletionCallback callback;
4889
4890 session_deps.socket_factory.ResetNextMockIndexes();
4891
4892 scoped_ptr<HttpTransaction> trans(
4893 new HttpNetworkTransaction(CreateSession(&session_deps)));
4894
[email protected]5a1d7ca2010-04-28 20:12:274895 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574896 EXPECT_EQ(ERR_IO_PENDING, rv);
4897
4898 rv = callback.WaitForResult();
4899 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4900}
4901
[email protected]e22e1362009-11-23 21:31:124902TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464903 SessionDependencies session_deps;
4904 scoped_ptr<HttpTransaction> trans(
4905 new HttpNetworkTransaction(CreateSession(&session_deps)));
4906
4907 HttpRequestInfo request;
4908 request.method = "GET";
4909 request.url = GURL("http://www.google.com/");
4910 request.load_flags = 0;
4911
[email protected]e22e1362009-11-23 21:31:124912 MockRead data_reads[] = {
4913 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4914 MockRead(false, OK),
4915 };
[email protected]9492e4a2010-02-24 00:58:464916
4917 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4918 session_deps.socket_factory.AddSocketDataProvider(&data);
4919
4920 TestCompletionCallback callback;
4921
[email protected]5a1d7ca2010-04-28 20:12:274922 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464923 EXPECT_EQ(ERR_IO_PENDING, rv);
4924
4925 EXPECT_EQ(OK, callback.WaitForResult());
4926
4927 const HttpResponseInfo* response = trans->GetResponseInfo();
4928 EXPECT_TRUE(response != NULL);
4929
4930 EXPECT_TRUE(response->headers != NULL);
4931 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4932
4933 std::string response_data;
4934 rv = ReadTransaction(trans.get(), &response_data);
4935 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124936}
4937
[email protected]95d88ffe2010-02-04 21:25:334938TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4939 SessionDependencies session_deps;
4940 scoped_ptr<HttpTransaction> trans(
4941 new HttpNetworkTransaction(CreateSession(&session_deps)));
4942
4943 HttpRequestInfo request;
4944 request.method = "POST";
4945 request.url = GURL("http://www.google.com/upload");
4946 request.upload_data = new UploadData;
4947 request.load_flags = 0;
4948
4949 FilePath temp_file_path;
4950 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4951 const uint64 kFakeSize = 100000; // file is actually blank
4952
4953 std::vector<UploadData::Element> elements;
4954 UploadData::Element element;
4955 element.SetToFilePath(temp_file_path);
4956 element.SetContentLength(kFakeSize);
4957 elements.push_back(element);
4958 request.upload_data->set_elements(elements);
4959 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4960
4961 MockRead data_reads[] = {
4962 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4963 MockRead("hello world"),
4964 MockRead(false, OK),
4965 };
[email protected]31a2bfe2010-02-09 08:03:394966 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334967 session_deps.socket_factory.AddSocketDataProvider(&data);
4968
4969 TestCompletionCallback callback;
4970
[email protected]5a1d7ca2010-04-28 20:12:274971 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334972 EXPECT_EQ(ERR_IO_PENDING, rv);
4973
4974 rv = callback.WaitForResult();
4975 EXPECT_EQ(OK, rv);
4976
4977 const HttpResponseInfo* response = trans->GetResponseInfo();
4978 EXPECT_TRUE(response != NULL);
4979
4980 EXPECT_TRUE(response->headers != NULL);
4981 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4982
4983 std::string response_data;
4984 rv = ReadTransaction(trans.get(), &response_data);
4985 EXPECT_EQ(OK, rv);
4986 EXPECT_EQ("hello world", response_data);
4987
4988 file_util::Delete(temp_file_path, false);
4989}
4990
[email protected]6624b4622010-03-29 19:58:364991TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4992 // If we try to upload an unreadable file, the network stack should report
4993 // the file size as zero and upload zero bytes for that file.
4994 SessionDependencies session_deps;
4995 scoped_ptr<HttpTransaction> trans(
4996 new HttpNetworkTransaction(CreateSession(&session_deps)));
4997
4998 FilePath temp_file;
4999 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5000 std::string temp_file_content("Unreadable file.");
5001 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5002 temp_file_content.length()));
5003 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5004
5005 HttpRequestInfo request;
5006 request.method = "POST";
5007 request.url = GURL("http://www.google.com/upload");
5008 request.upload_data = new UploadData;
5009 request.load_flags = 0;
5010
5011 std::vector<UploadData::Element> elements;
5012 UploadData::Element element;
5013 element.SetToFilePath(temp_file);
5014 elements.push_back(element);
5015 request.upload_data->set_elements(elements);
5016
5017 MockRead data_reads[] = {
5018 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5019 MockRead(false, OK),
5020 };
5021 MockWrite data_writes[] = {
5022 MockWrite("POST /upload HTTP/1.1\r\n"
5023 "Host: www.google.com\r\n"
5024 "Connection: keep-alive\r\n"
5025 "Content-Length: 0\r\n\r\n"),
5026 MockWrite(false, OK),
5027 };
5028 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5029 arraysize(data_writes));
5030 session_deps.socket_factory.AddSocketDataProvider(&data);
5031
5032 TestCompletionCallback callback;
5033
[email protected]5a1d7ca2010-04-28 20:12:275034 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365035 EXPECT_EQ(ERR_IO_PENDING, rv);
5036
5037 rv = callback.WaitForResult();
5038 EXPECT_EQ(OK, rv);
5039
5040 const HttpResponseInfo* response = trans->GetResponseInfo();
5041 EXPECT_TRUE(response != NULL);
5042 EXPECT_TRUE(response->headers != NULL);
5043 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5044
5045 file_util::Delete(temp_file, false);
5046}
5047
5048TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5049 SessionDependencies session_deps;
5050 scoped_ptr<HttpTransaction> trans(
5051 new HttpNetworkTransaction(CreateSession(&session_deps)));
5052
5053 FilePath temp_file;
5054 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5055 std::string temp_file_contents("Unreadable file.");
5056 std::string unreadable_contents(temp_file_contents.length(), '\0');
5057 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5058 temp_file_contents.length()));
5059
5060 HttpRequestInfo request;
5061 request.method = "POST";
5062 request.url = GURL("http://www.google.com/upload");
5063 request.upload_data = new UploadData;
5064 request.load_flags = 0;
5065
5066 std::vector<UploadData::Element> elements;
5067 UploadData::Element element;
5068 element.SetToFilePath(temp_file);
5069 elements.push_back(element);
5070 request.upload_data->set_elements(elements);
5071
5072 MockRead data_reads[] = {
5073 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5074 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5075 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5076
5077 MockRead("HTTP/1.1 200 OK\r\n"),
5078 MockRead("Content-Length: 0\r\n\r\n"),
5079 MockRead(false, OK),
5080 };
5081 MockWrite data_writes[] = {
5082 MockWrite("POST /upload HTTP/1.1\r\n"
5083 "Host: www.google.com\r\n"
5084 "Connection: keep-alive\r\n"
5085 "Content-Length: 16\r\n\r\n"),
5086 MockWrite(false, temp_file_contents.c_str()),
5087
5088 MockWrite("POST /upload HTTP/1.1\r\n"
5089 "Host: www.google.com\r\n"
5090 "Connection: keep-alive\r\n"
5091 "Content-Length: 16\r\n"
5092 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5093 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5094 MockWrite(false, OK),
5095 };
5096 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5097 arraysize(data_writes));
5098 session_deps.socket_factory.AddSocketDataProvider(&data);
5099
5100 TestCompletionCallback callback1;
5101
[email protected]5a1d7ca2010-04-28 20:12:275102 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365103 EXPECT_EQ(ERR_IO_PENDING, rv);
5104
5105 rv = callback1.WaitForResult();
5106 EXPECT_EQ(OK, rv);
5107
5108 const HttpResponseInfo* response = trans->GetResponseInfo();
5109 EXPECT_TRUE(response != NULL);
5110 EXPECT_TRUE(response->headers != NULL);
5111 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5112
5113 // The password prompt info should have been set in response->auth_challenge.
5114 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5115 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5116 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5117 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5118
5119 // Now make the file unreadable and try again.
5120 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5121
5122 TestCompletionCallback callback2;
5123
[email protected]13c8a092010-07-29 06:15:445124 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365125 EXPECT_EQ(ERR_IO_PENDING, rv);
5126
5127 rv = callback2.WaitForResult();
5128 EXPECT_EQ(OK, rv);
5129
5130 response = trans->GetResponseInfo();
5131 EXPECT_TRUE(response != NULL);
5132 EXPECT_TRUE(response->headers != NULL);
5133 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5134 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5135
5136 file_util::Delete(temp_file, false);
5137}
5138
[email protected]aeefc9e82010-02-19 16:18:275139// Tests that changes to Auth realms are treated like auth rejections.
5140TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5141 SessionDependencies session_deps;
5142 scoped_ptr<HttpTransaction> trans(
5143 new HttpNetworkTransaction(CreateSession(&session_deps)));
5144
5145 HttpRequestInfo request;
5146 request.method = "GET";
5147 request.url = GURL("http://www.google.com/");
5148 request.load_flags = 0;
5149
5150 // First transaction will request a resource and receive a Basic challenge
5151 // with realm="first_realm".
5152 MockWrite data_writes1[] = {
5153 MockWrite("GET / HTTP/1.1\r\n"
5154 "Host: www.google.com\r\n"
5155 "Connection: keep-alive\r\n"
5156 "\r\n"),
5157 };
5158 MockRead data_reads1[] = {
5159 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5160 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5161 "\r\n"),
5162 };
5163
5164 // After calling trans->RestartWithAuth(), provide an Authentication header
5165 // for first_realm. The server will reject and provide a challenge with
5166 // second_realm.
5167 MockWrite data_writes2[] = {
5168 MockWrite("GET / HTTP/1.1\r\n"
5169 "Host: www.google.com\r\n"
5170 "Connection: keep-alive\r\n"
5171 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5172 "\r\n"),
5173 };
5174 MockRead data_reads2[] = {
5175 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5176 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5177 "\r\n"),
5178 };
5179
5180 // This again fails, and goes back to first_realm. Make sure that the
5181 // entry is removed from cache.
5182 MockWrite data_writes3[] = {
5183 MockWrite("GET / HTTP/1.1\r\n"
5184 "Host: www.google.com\r\n"
5185 "Connection: keep-alive\r\n"
5186 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5187 "\r\n"),
5188 };
5189 MockRead data_reads3[] = {
5190 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5191 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5192 "\r\n"),
5193 };
5194
5195 // Try one last time (with the correct password) and get the resource.
5196 MockWrite data_writes4[] = {
5197 MockWrite("GET / HTTP/1.1\r\n"
5198 "Host: www.google.com\r\n"
5199 "Connection: keep-alive\r\n"
5200 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5201 "\r\n"),
5202 };
5203 MockRead data_reads4[] = {
5204 MockRead("HTTP/1.1 200 OK\r\n"
5205 "Content-Type: text/html; charset=iso-8859-1\r\n"
5206 "Content-Length: 100\r\n"
5207 "\r\n"),
5208 };
5209
5210 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5211 data_writes1, arraysize(data_writes1));
5212 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5213 data_writes2, arraysize(data_writes2));
5214 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5215 data_writes3, arraysize(data_writes3));
5216 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5217 data_writes4, arraysize(data_writes4));
5218 session_deps.socket_factory.AddSocketDataProvider(&data1);
5219 session_deps.socket_factory.AddSocketDataProvider(&data2);
5220 session_deps.socket_factory.AddSocketDataProvider(&data3);
5221 session_deps.socket_factory.AddSocketDataProvider(&data4);
5222
5223 TestCompletionCallback callback1;
5224
5225 // Issue the first request with Authorize headers. There should be a
5226 // password prompt for first_realm waiting to be filled in after the
5227 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275228 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275229 EXPECT_EQ(ERR_IO_PENDING, rv);
5230 rv = callback1.WaitForResult();
5231 EXPECT_EQ(OK, rv);
5232 const HttpResponseInfo* response = trans->GetResponseInfo();
5233 ASSERT_FALSE(response == NULL);
5234 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5235 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5236 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5237 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5238
5239 // Issue the second request with an incorrect password. There should be a
5240 // password prompt for second_realm waiting to be filled in after the
5241 // transaction completes.
5242 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445243 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275244 EXPECT_EQ(ERR_IO_PENDING, rv);
5245 rv = callback2.WaitForResult();
5246 EXPECT_EQ(OK, rv);
5247 response = trans->GetResponseInfo();
5248 ASSERT_FALSE(response == NULL);
5249 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5250 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5251 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5252 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5253
5254 // Issue the third request with another incorrect password. There should be
5255 // a password prompt for first_realm waiting to be filled in. If the password
5256 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5257 // first_realm was not correctly removed.
5258 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445259 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275260 EXPECT_EQ(ERR_IO_PENDING, rv);
5261 rv = callback3.WaitForResult();
5262 EXPECT_EQ(OK, rv);
5263 response = trans->GetResponseInfo();
5264 ASSERT_FALSE(response == NULL);
5265 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5266 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5267 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5268 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5269
5270 // Issue the fourth request with the correct password and username.
5271 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445272 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275273 EXPECT_EQ(ERR_IO_PENDING, rv);
5274 rv = callback4.WaitForResult();
5275 EXPECT_EQ(OK, rv);
5276 response = trans->GetResponseInfo();
5277 ASSERT_FALSE(response == NULL);
5278 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5279}
5280
[email protected]564b4912010-03-09 16:30:425281TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:385282 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
5283 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:425284
[email protected]564b4912010-03-09 16:30:425285 SessionDependencies session_deps;
5286
5287 MockRead data_reads[] = {
5288 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355289 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425290 MockRead("hello world"),
5291 MockRead(false, OK),
5292 };
5293
5294 HttpRequestInfo request;
5295 request.method = "GET";
5296 request.url = GURL("http://www.google.com/");
5297 request.load_flags = 0;
5298
5299 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5300
5301 session_deps.socket_factory.AddSocketDataProvider(&data);
5302
5303 TestCompletionCallback callback;
5304
5305 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5306 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5307
[email protected]5a1d7ca2010-04-28 20:12:275308 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425309 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535310
[email protected]2fbaecf22010-07-22 22:20:355311 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425312 const HttpAlternateProtocols& alternate_protocols =
5313 session->alternate_protocols();
5314 EXPECT_FALSE(
5315 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5316
5317 EXPECT_EQ(OK, callback.WaitForResult());
5318
5319 const HttpResponseInfo* response = trans->GetResponseInfo();
5320 ASSERT_TRUE(response != NULL);
5321 ASSERT_TRUE(response->headers != NULL);
5322 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535323 EXPECT_FALSE(response->was_fetched_via_spdy);
5324 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575325 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425326
5327 std::string response_data;
5328 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5329 EXPECT_EQ("hello world", response_data);
5330
5331 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5332 const HttpAlternateProtocols::PortProtocolPair alternate =
5333 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5334 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5335 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355336 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425337 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425338
[email protected]8e6441ca2010-08-19 05:56:385339 HttpStreamFactory::set_use_alternate_protocols(false);
5340 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:425341}
5342
5343TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:385344 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:425345 SessionDependencies session_deps;
5346
5347 HttpRequestInfo request;
5348 request.method = "GET";
5349 request.url = GURL("http://www.google.com/");
5350 request.load_flags = 0;
5351
5352 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5353 StaticSocketDataProvider first_data;
5354 first_data.set_connect_data(mock_connect);
5355 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5356
5357 MockRead data_reads[] = {
5358 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5359 MockRead("hello world"),
5360 MockRead(true, OK),
5361 };
5362 StaticSocketDataProvider second_data(
5363 data_reads, arraysize(data_reads), NULL, 0);
5364 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5365
5366 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5367 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5368 // http://crbug.com/37454.
5369 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5370
5371 TestCompletionCallback callback;
5372
5373 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5374
[email protected]2fbaecf22010-07-22 22:20:355375 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425376 HttpAlternateProtocols* alternate_protocols =
5377 session->mutable_alternate_protocols();
5378 alternate_protocols->SetAlternateProtocolFor(
5379 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355380 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425381
5382 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5383
[email protected]5a1d7ca2010-04-28 20:12:275384 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425385 EXPECT_EQ(ERR_IO_PENDING, rv);
5386 EXPECT_EQ(OK, callback.WaitForResult());
5387
5388 const HttpResponseInfo* response = trans->GetResponseInfo();
5389 ASSERT_TRUE(response != NULL);
5390 ASSERT_TRUE(response->headers != NULL);
5391 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5392
5393 std::string response_data;
5394 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5395 EXPECT_EQ("hello world", response_data);
5396
5397 ASSERT_TRUE(
5398 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5399 const HttpAlternateProtocols::PortProtocolPair alternate =
5400 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5401 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:385402 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:425403}
5404
5405// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5406// says that it does SPDY, but it just does the TLS handshake, but the NPN
5407// response does not indicate SPDY, so we just do standard HTTPS over the port.
5408// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5409// on the original port.
[email protected]a2cb8122010-03-10 17:22:425410// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5411// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535412//
[email protected]a2cb8122010-03-10 17:22:425413// HttpRequestInfo request;
5414// request.method = "GET";
5415// request.url = GURL("http://www.google.com/");
5416// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535417//
[email protected]a2cb8122010-03-10 17:22:425418// MockRead data_reads[] = {
5419// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5420// MockRead("hello world"),
5421// MockRead(true, OK),
5422// };
5423// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5424// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535425//
[email protected]a2cb8122010-03-10 17:22:425426// SSLSocketDataProvider ssl(true, OK);
5427// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535428//
[email protected]a2cb8122010-03-10 17:22:425429// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535430//
[email protected]a2cb8122010-03-10 17:22:425431// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535432//
[email protected]a2cb8122010-03-10 17:22:425433// HostPortPair http_host_port_pair;
5434// http_host_port_pair.host = "www.google.com";
5435// http_host_port_pair.port = 80;
5436// HttpAlternateProtocols* alternate_protocols =
5437// session->mutable_alternate_protocols();
5438// alternate_protocols->SetAlternateProtocolFor(
5439// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065440// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535441//
[email protected]a2cb8122010-03-10 17:22:425442// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535443//
[email protected]5a1d7ca2010-04-28 20:12:275444// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425445// EXPECT_EQ(ERR_IO_PENDING, rv);
5446// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535447//
[email protected]a2cb8122010-03-10 17:22:425448// const HttpResponseInfo* response = trans->GetResponseInfo();
5449// ASSERT_TRUE(response != NULL);
5450// ASSERT_TRUE(response->headers != NULL);
5451// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535452//
[email protected]a2cb8122010-03-10 17:22:425453// std::string response_data;
5454// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5455// EXPECT_EQ("hello world", response_data);
5456// }
5457
5458TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:385459 HttpStreamFactory::set_use_alternate_protocols(true);
5460 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425461 SessionDependencies session_deps;
5462
5463 HttpRequestInfo request;
5464 request.method = "GET";
5465 request.url = GURL("http://www.google.com/");
5466 request.load_flags = 0;
5467
[email protected]a2cb8122010-03-10 17:22:425468 StaticSocketDataProvider first_tcp_connect;
5469 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5470
5471 SSLSocketDataProvider ssl(true, OK);
5472 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5473
[email protected]564b4912010-03-09 16:30:425474 MockRead data_reads[] = {
5475 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5476 MockRead("hello world"),
5477 MockRead(true, OK),
5478 };
[email protected]a2cb8122010-03-10 17:22:425479 StaticSocketDataProvider fallback_data(
5480 data_reads, arraysize(data_reads), NULL, 0);
5481 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425482
5483 TestCompletionCallback callback;
5484
5485 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5486
[email protected]2fbaecf22010-07-22 22:20:355487 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425488 HttpAlternateProtocols* alternate_protocols =
5489 session->mutable_alternate_protocols();
5490 alternate_protocols->SetAlternateProtocolFor(
5491 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355492 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425493
5494 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5495
[email protected]5a1d7ca2010-04-28 20:12:275496 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425497 EXPECT_EQ(ERR_IO_PENDING, rv);
5498 EXPECT_EQ(OK, callback.WaitForResult());
5499
5500 const HttpResponseInfo* response = trans->GetResponseInfo();
5501 ASSERT_TRUE(response != NULL);
5502 ASSERT_TRUE(response->headers != NULL);
5503 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5504
5505 std::string response_data;
5506 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5507 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:385508 HttpStreamFactory::set_next_protos("");
5509 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:545510}
5511
5512TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:385513 HttpStreamFactory::set_use_alternate_protocols(true);
5514 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545515 SessionDependencies session_deps;
5516
5517 HttpRequestInfo request;
5518 request.method = "GET";
5519 request.url = GURL("http://www.google.com/");
5520 request.load_flags = 0;
5521
5522 MockRead data_reads[] = {
5523 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355524 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545525 MockRead("hello world"),
5526 MockRead(true, OK),
5527 };
5528
5529 StaticSocketDataProvider first_transaction(
5530 data_reads, arraysize(data_reads), NULL, 0);
5531 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5532
5533 SSLSocketDataProvider ssl(true, OK);
5534 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355535 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535536 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545537 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5538
[email protected]2bd93022010-07-17 00:58:445539 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135540 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545541
[email protected]2bd93022010-07-17 00:58:445542 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5543 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545544 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135545 CreateMockRead(*resp),
5546 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545547 MockRead(true, 0, 0),
5548 };
5549
5550 scoped_refptr<DelayedSocketData> spdy_data(
5551 new DelayedSocketData(
5552 1, // wait for one write to finish before reading.
5553 spdy_reads, arraysize(spdy_reads),
5554 spdy_writes, arraysize(spdy_writes)));
5555 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5556
5557 TestCompletionCallback callback;
5558
5559 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5560 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5561
[email protected]5a1d7ca2010-04-28 20:12:275562 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545563 EXPECT_EQ(ERR_IO_PENDING, rv);
5564 EXPECT_EQ(OK, callback.WaitForResult());
5565
5566 const HttpResponseInfo* response = trans->GetResponseInfo();
5567 ASSERT_TRUE(response != NULL);
5568 ASSERT_TRUE(response->headers != NULL);
5569 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5570
5571 std::string response_data;
5572 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5573 EXPECT_EQ("hello world", response_data);
5574
5575 trans.reset(new HttpNetworkTransaction(session));
5576
[email protected]5a1d7ca2010-04-28 20:12:275577 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545578 EXPECT_EQ(ERR_IO_PENDING, rv);
5579 EXPECT_EQ(OK, callback.WaitForResult());
5580
5581 response = trans->GetResponseInfo();
5582 ASSERT_TRUE(response != NULL);
5583 ASSERT_TRUE(response->headers != NULL);
5584 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535585 EXPECT_TRUE(response->was_fetched_via_spdy);
5586 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575587 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545588
5589 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5590 EXPECT_EQ("hello!", response_data);
5591
[email protected]8e6441ca2010-08-19 05:56:385592 HttpStreamFactory::set_next_protos("");
5593 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:545594}
5595
[email protected]631f1322010-04-30 17:59:115596class CapturingProxyResolver : public ProxyResolver {
5597 public:
5598 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5599 virtual ~CapturingProxyResolver() {}
5600
5601 virtual int GetProxyForURL(const GURL& url,
5602 ProxyInfo* results,
5603 CompletionCallback* callback,
5604 RequestHandle* request,
5605 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:405606 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
5607 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:425608 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115609 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425610 return OK;
[email protected]631f1322010-04-30 17:59:115611 }
5612
5613 virtual void CancelRequest(RequestHandle request) {
5614 NOTREACHED();
5615 }
5616
[email protected]24476402010-07-20 20:55:175617 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:115618 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425619 return OK;
[email protected]631f1322010-04-30 17:59:115620 }
5621
[email protected]24476402010-07-20 20:55:175622 const std::vector<GURL>& resolved() const { return resolved_; }
5623
5624 private:
[email protected]631f1322010-04-30 17:59:115625 std::vector<GURL> resolved_;
5626
5627 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5628};
5629
[email protected]631f1322010-04-30 17:59:115630TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:385631 HttpStreamFactory::set_use_alternate_protocols(true);
5632 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:115633
5634 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425635 proxy_config.set_auto_detect(true);
5636 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115637
[email protected]631f1322010-04-30 17:59:115638 CapturingProxyResolver* capturing_proxy_resolver =
5639 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385640 SessionDependencies session_deps(new ProxyService(
5641 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5642 NULL));
[email protected]631f1322010-04-30 17:59:115643
5644 HttpRequestInfo request;
5645 request.method = "GET";
5646 request.url = GURL("http://www.google.com/");
5647 request.load_flags = 0;
5648
5649 MockRead data_reads[] = {
5650 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355651 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:115652 MockRead("hello world"),
5653 MockRead(true, OK),
5654 };
5655
5656 StaticSocketDataProvider first_transaction(
5657 data_reads, arraysize(data_reads), NULL, 0);
5658 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5659
5660 SSLSocketDataProvider ssl(true, OK);
5661 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355662 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535663 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115664 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5665
[email protected]2bd93022010-07-17 00:58:445666 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:115667 MockWrite spdy_writes[] = {
5668 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5669 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425670 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135671 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115672 };
5673
[email protected]d911f1b2010-05-05 22:39:425674 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5675
[email protected]2bd93022010-07-17 00:58:445676 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5677 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:115678 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425679 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135680 CreateMockRead(*resp.get(), 4), // 2, 4
5681 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425682 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115683 };
5684
[email protected]d911f1b2010-05-05 22:39:425685 scoped_refptr<OrderedSocketData> spdy_data(
5686 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115687 spdy_reads, arraysize(spdy_reads),
5688 spdy_writes, arraysize(spdy_writes)));
5689 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5690
5691 TestCompletionCallback callback;
5692
5693 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5694 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5695
5696 int rv = trans->Start(&request, &callback, BoundNetLog());
5697 EXPECT_EQ(ERR_IO_PENDING, rv);
5698 EXPECT_EQ(OK, callback.WaitForResult());
5699
5700 const HttpResponseInfo* response = trans->GetResponseInfo();
5701 ASSERT_TRUE(response != NULL);
5702 ASSERT_TRUE(response->headers != NULL);
5703 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535704 EXPECT_FALSE(response->was_fetched_via_spdy);
5705 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115706
5707 std::string response_data;
5708 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5709 EXPECT_EQ("hello world", response_data);
5710
5711 trans.reset(new HttpNetworkTransaction(session));
5712
5713 rv = trans->Start(&request, &callback, BoundNetLog());
5714 EXPECT_EQ(ERR_IO_PENDING, rv);
5715 EXPECT_EQ(OK, callback.WaitForResult());
5716
5717 response = trans->GetResponseInfo();
5718 ASSERT_TRUE(response != NULL);
5719 ASSERT_TRUE(response->headers != NULL);
5720 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535721 EXPECT_TRUE(response->was_fetched_via_spdy);
5722 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115723
5724 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5725 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425726 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5727 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115728 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425729 EXPECT_EQ("https://www.google.com/",
5730 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115731
[email protected]8e6441ca2010-08-19 05:56:385732 HttpStreamFactory::set_next_protos("");
5733 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:115734}
[email protected]631f1322010-04-30 17:59:115735
[email protected]2ff8b312010-04-26 22:20:545736TEST_F(HttpNetworkTransactionTest,
5737 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:385738 HttpStreamFactory::set_use_alternate_protocols(true);
5739 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545740 SessionDependencies session_deps;
5741
5742 HttpRequestInfo request;
5743 request.method = "GET";
5744 request.url = GURL("http://www.google.com/");
5745 request.load_flags = 0;
5746
5747 MockRead data_reads[] = {
5748 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355749 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545750 MockRead("hello world"),
5751 MockRead(true, OK),
5752 };
5753
5754 StaticSocketDataProvider first_transaction(
5755 data_reads, arraysize(data_reads), NULL, 0);
5756 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5757
5758 SSLSocketDataProvider ssl(true, OK);
5759 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355760 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535761 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545762 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535763 // Make sure we use ssl for spdy here.
5764 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545765
[email protected]2bd93022010-07-17 00:58:445766 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135767 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545768
[email protected]2bd93022010-07-17 00:58:445769 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5770 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545771 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135772 CreateMockRead(*resp),
5773 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545774 MockRead(true, 0, 0),
5775 };
5776
5777 scoped_refptr<DelayedSocketData> spdy_data(
5778 new DelayedSocketData(
5779 1, // wait for one write to finish before reading.
5780 spdy_reads, arraysize(spdy_reads),
5781 spdy_writes, arraysize(spdy_writes)));
5782 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5783
5784 TestCompletionCallback callback;
5785
5786 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5787
5788 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5789
[email protected]5a1d7ca2010-04-28 20:12:275790 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545791 EXPECT_EQ(ERR_IO_PENDING, rv);
5792 EXPECT_EQ(OK, callback.WaitForResult());
5793
5794 const HttpResponseInfo* response = trans->GetResponseInfo();
5795 ASSERT_TRUE(response != NULL);
5796 ASSERT_TRUE(response->headers != NULL);
5797 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5798
5799 std::string response_data;
5800 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5801 EXPECT_EQ("hello world", response_data);
5802
5803 // Set up an initial SpdySession in the pool to reuse.
[email protected]b261d0e2010-08-02 19:13:245804 HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT");
[email protected]2ff8b312010-04-26 22:20:545805 scoped_refptr<SpdySession> spdy_session =
[email protected]b261d0e2010-08-02 19:13:245806 session->spdy_session_pool()->Get(pair, session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215807 scoped_refptr<TCPSocketParams> tcp_params =
5808 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365809 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545810 trans.reset(new HttpNetworkTransaction(session));
5811
[email protected]5a1d7ca2010-04-28 20:12:275812 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545813 EXPECT_EQ(ERR_IO_PENDING, rv);
5814 EXPECT_EQ(OK, callback.WaitForResult());
5815
5816 response = trans->GetResponseInfo();
5817 ASSERT_TRUE(response != NULL);
5818 ASSERT_TRUE(response->headers != NULL);
5819 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535820 EXPECT_TRUE(response->was_fetched_via_spdy);
5821 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575822 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545823
5824 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5825 EXPECT_EQ("hello!", response_data);
5826
[email protected]8e6441ca2010-08-19 05:56:385827 HttpStreamFactory::set_next_protos("");
5828 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:425829}
5830
[email protected]044de0642010-06-17 10:42:155831// GenerateAuthToken is a mighty big test.
5832// It tests all permutation of GenerateAuthToken behavior:
5833// - Synchronous and Asynchronous completion.
5834// - OK or error on completion.
5835// - Direct connection, non-authenticating proxy, and authenticating proxy.
5836// - HTTP or HTTPS backend (to include proxy tunneling).
5837// - Non-authenticating and authenticating backend.
5838//
5839// In all, there are 44 reasonable permuations (for example, if there are
5840// problems generating an auth token for an authenticating proxy, we don't
5841// need to test all permutations of the backend server).
5842//
5843// The test proceeds by going over each of the configuration cases, and
5844// potentially running up to three rounds in each of the tests. The TestConfig
5845// specifies both the configuration for the test as well as the expectations
5846// for the results.
5847TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5848 const char* kServer = "http://www.example.com";
5849 const char* kSecureServer = "https://www.example.com";
5850 const char* kProxy = "myproxy:70";
5851 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5852
5853 enum AuthTiming {
5854 AUTH_NONE,
5855 AUTH_SYNC,
5856 AUTH_ASYNC,
5857 };
5858
5859 const MockWrite kGet(
5860 "GET / HTTP/1.1\r\n"
5861 "Host: www.example.com\r\n"
5862 "Connection: keep-alive\r\n\r\n");
5863 const MockWrite kGetProxy(
5864 "GET http://www.example.com/ HTTP/1.1\r\n"
5865 "Host: www.example.com\r\n"
5866 "Proxy-Connection: keep-alive\r\n\r\n");
5867 const MockWrite kGetAuth(
5868 "GET / HTTP/1.1\r\n"
5869 "Host: www.example.com\r\n"
5870 "Connection: keep-alive\r\n"
5871 "Authorization: auth_token\r\n\r\n");
5872 const MockWrite kGetProxyAuth(
5873 "GET http://www.example.com/ HTTP/1.1\r\n"
5874 "Host: www.example.com\r\n"
5875 "Proxy-Connection: keep-alive\r\n"
5876 "Proxy-Authorization: auth_token\r\n\r\n");
5877 const MockWrite kGetAuthThroughProxy(
5878 "GET http://www.example.com/ HTTP/1.1\r\n"
5879 "Host: www.example.com\r\n"
5880 "Proxy-Connection: keep-alive\r\n"
5881 "Authorization: auth_token\r\n\r\n");
5882 const MockWrite kGetAuthWithProxyAuth(
5883 "GET http://www.example.com/ HTTP/1.1\r\n"
5884 "Host: www.example.com\r\n"
5885 "Proxy-Connection: keep-alive\r\n"
5886 "Proxy-Authorization: auth_token\r\n"
5887 "Authorization: auth_token\r\n\r\n");
5888 const MockWrite kConnect(
5889 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5890 "Host: www.example.com\r\n"
5891 "Proxy-Connection: keep-alive\r\n\r\n");
5892 const MockWrite kConnectProxyAuth(
5893 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5894 "Host: www.example.com\r\n"
5895 "Proxy-Connection: keep-alive\r\n"
5896 "Proxy-Authorization: auth_token\r\n\r\n");
5897
5898 const MockRead kSuccess(
5899 "HTTP/1.1 200 OK\r\n"
5900 "Content-Type: text/html; charset=iso-8859-1\r\n"
5901 "Content-Length: 3\r\n\r\n"
5902 "Yes");
5903 const MockRead kFailure(
5904 "Should not be called.");
5905 const MockRead kServerChallenge(
5906 "HTTP/1.1 401 Unauthorized\r\n"
5907 "WWW-Authenticate: Mock realm=server\r\n"
5908 "Content-Type: text/html; charset=iso-8859-1\r\n"
5909 "Content-Length: 14\r\n\r\n"
5910 "Unauthorized\r\n");
5911 const MockRead kProxyChallenge(
5912 "HTTP/1.1 407 Unauthorized\r\n"
5913 "Proxy-Authenticate: Mock realm=proxy\r\n"
5914 "Proxy-Connection: close\r\n"
5915 "Content-Type: text/html; charset=iso-8859-1\r\n"
5916 "Content-Length: 14\r\n\r\n"
5917 "Unauthorized\r\n");
5918 const MockRead kProxyConnected(
5919 "HTTP/1.1 200 Connection Established\r\n\r\n");
5920
5921 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5922 // no constructors, but the C++ compiler on Windows warns about
5923 // unspecified data in compound literals. So, moved to using constructors,
5924 // and TestRound's created with the default constructor should not be used.
5925 struct TestRound {
5926 TestRound()
5927 : expected_rv(ERR_UNEXPECTED),
5928 extra_write(NULL),
5929 extra_read(NULL) {
5930 }
5931 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5932 int expected_rv_arg)
5933 : write(write_arg),
5934 read(read_arg),
5935 expected_rv(expected_rv_arg),
5936 extra_write(NULL),
5937 extra_read(NULL) {
5938 }
5939 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5940 int expected_rv_arg, const MockWrite* extra_write_arg,
5941 const MockWrite* extra_read_arg)
5942 : write(write_arg),
5943 read(read_arg),
5944 expected_rv(expected_rv_arg),
5945 extra_write(extra_write_arg),
5946 extra_read(extra_read_arg) {
5947 }
5948 MockWrite write;
5949 MockRead read;
5950 int expected_rv;
5951 const MockWrite* extra_write;
5952 const MockRead* extra_read;
5953 };
5954
5955 static const int kNoSSL = 500;
5956
5957 struct TestConfig {
5958 const char* proxy_url;
5959 AuthTiming proxy_auth_timing;
5960 int proxy_auth_rv;
5961 const char* server_url;
5962 AuthTiming server_auth_timing;
5963 int server_auth_rv;
5964 int num_auth_rounds;
5965 int first_ssl_round;
5966 TestRound rounds[3];
5967 } test_configs[] = {
5968 // Non-authenticating HTTP server with a direct connection.
5969 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5970 { TestRound(kGet, kSuccess, OK)}},
5971 // Authenticating HTTP server with a direct connection.
5972 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5973 { TestRound(kGet, kServerChallenge, OK),
5974 TestRound(kGetAuth, kSuccess, OK)}},
5975 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5976 { TestRound(kGet, kServerChallenge, OK),
5977 TestRound(kGetAuth, kFailure, kAuthErr)}},
5978 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5979 { TestRound(kGet, kServerChallenge, OK),
5980 TestRound(kGetAuth, kSuccess, OK)}},
5981 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5982 { TestRound(kGet, kServerChallenge, OK),
5983 TestRound(kGetAuth, kFailure, kAuthErr)}},
5984 // Non-authenticating HTTP server through a non-authenticating proxy.
5985 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5986 { TestRound(kGetProxy, kSuccess, OK)}},
5987 // Authenticating HTTP server through a non-authenticating proxy.
5988 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5989 { TestRound(kGetProxy, kServerChallenge, OK),
5990 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5991 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5992 { TestRound(kGetProxy, kServerChallenge, OK),
5993 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5994 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5995 { TestRound(kGetProxy, kServerChallenge, OK),
5996 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5997 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5998 { TestRound(kGetProxy, kServerChallenge, OK),
5999 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6000 // Non-authenticating HTTP server through an authenticating proxy.
6001 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6002 { TestRound(kGetProxy, kProxyChallenge, OK),
6003 TestRound(kGetProxyAuth, kSuccess, OK)}},
6004 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6005 { TestRound(kGetProxy, kProxyChallenge, OK),
6006 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6007 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6008 { TestRound(kGetProxy, kProxyChallenge, OK),
6009 TestRound(kGetProxyAuth, kSuccess, OK)}},
6010 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6011 { TestRound(kGetProxy, kProxyChallenge, OK),
6012 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6013 // Authenticating HTTP server through an authenticating proxy.
6014 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6015 { TestRound(kGetProxy, kProxyChallenge, OK),
6016 TestRound(kGetProxyAuth, kServerChallenge, OK),
6017 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6018 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6019 { TestRound(kGetProxy, kProxyChallenge, OK),
6020 TestRound(kGetProxyAuth, kServerChallenge, OK),
6021 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6022 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6023 { TestRound(kGetProxy, kProxyChallenge, OK),
6024 TestRound(kGetProxyAuth, kServerChallenge, OK),
6025 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6026 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6027 { TestRound(kGetProxy, kProxyChallenge, OK),
6028 TestRound(kGetProxyAuth, kServerChallenge, OK),
6029 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6030 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6031 { TestRound(kGetProxy, kProxyChallenge, OK),
6032 TestRound(kGetProxyAuth, kServerChallenge, OK),
6033 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6034 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6035 { TestRound(kGetProxy, kProxyChallenge, OK),
6036 TestRound(kGetProxyAuth, kServerChallenge, OK),
6037 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6038 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6039 { TestRound(kGetProxy, kProxyChallenge, OK),
6040 TestRound(kGetProxyAuth, kServerChallenge, OK),
6041 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6042 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6043 { TestRound(kGetProxy, kProxyChallenge, OK),
6044 TestRound(kGetProxyAuth, kServerChallenge, OK),
6045 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6046 // Non-authenticating HTTPS server with a direct connection.
6047 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6048 { TestRound(kGet, kSuccess, OK)}},
6049 // Authenticating HTTPS server with a direct connection.
6050 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6051 { TestRound(kGet, kServerChallenge, OK),
6052 TestRound(kGetAuth, kSuccess, OK)}},
6053 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6054 { TestRound(kGet, kServerChallenge, OK),
6055 TestRound(kGetAuth, kFailure, kAuthErr)}},
6056 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6057 { TestRound(kGet, kServerChallenge, OK),
6058 TestRound(kGetAuth, kSuccess, OK)}},
6059 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6060 { TestRound(kGet, kServerChallenge, OK),
6061 TestRound(kGetAuth, kFailure, kAuthErr)}},
6062 // Non-authenticating HTTPS server with a non-authenticating proxy.
6063 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6064 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6065 // Authenticating HTTPS server through a non-authenticating proxy.
6066 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6067 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6068 TestRound(kGetAuth, kSuccess, OK)}},
6069 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6070 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6071 TestRound(kGetAuth, kFailure, kAuthErr)}},
6072 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6073 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6074 TestRound(kGetAuth, kSuccess, OK)}},
6075 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6076 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6077 TestRound(kGetAuth, kFailure, kAuthErr)}},
6078 // Non-Authenticating HTTPS server through an authenticating proxy.
6079 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6080 { TestRound(kConnect, kProxyChallenge, OK),
6081 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6082 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6083 { TestRound(kConnect, kProxyChallenge, OK),
6084 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6085 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6086 { TestRound(kConnect, kProxyChallenge, OK),
6087 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6088 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6089 { TestRound(kConnect, kProxyChallenge, OK),
6090 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6091 // Authenticating HTTPS server through an authenticating proxy.
6092 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6093 { TestRound(kConnect, kProxyChallenge, OK),
6094 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6095 &kGet, &kServerChallenge),
6096 TestRound(kGetAuth, kSuccess, OK)}},
6097 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6098 { TestRound(kConnect, kProxyChallenge, OK),
6099 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6100 &kGet, &kServerChallenge),
6101 TestRound(kGetAuth, kFailure, kAuthErr)}},
6102 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6103 { TestRound(kConnect, kProxyChallenge, OK),
6104 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6105 &kGet, &kServerChallenge),
6106 TestRound(kGetAuth, kSuccess, OK)}},
6107 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6108 { TestRound(kConnect, kProxyChallenge, OK),
6109 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6110 &kGet, &kServerChallenge),
6111 TestRound(kGetAuth, kFailure, kAuthErr)}},
6112 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6113 { TestRound(kConnect, kProxyChallenge, OK),
6114 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6115 &kGet, &kServerChallenge),
6116 TestRound(kGetAuth, kSuccess, OK)}},
6117 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6118 { TestRound(kConnect, kProxyChallenge, OK),
6119 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6120 &kGet, &kServerChallenge),
6121 TestRound(kGetAuth, kFailure, kAuthErr)}},
6122 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6123 { TestRound(kConnect, kProxyChallenge, OK),
6124 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6125 &kGet, &kServerChallenge),
6126 TestRound(kGetAuth, kSuccess, OK)}},
6127 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6128 { TestRound(kConnect, kProxyChallenge, OK),
6129 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6130 &kGet, &kServerChallenge),
6131 TestRound(kGetAuth, kFailure, kAuthErr)}},
6132 };
6133
6134 SessionDependencies session_deps;
6135 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:006136 HttpAuthHandlerMock::Factory* auth_factory(
6137 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156138 session_deps.http_auth_handler_factory.reset(auth_factory);
6139
6140 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6141 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266142
6143 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156144 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006145 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156146 std::string auth_challenge = "Mock realm=proxy";
6147 GURL origin(test_config.proxy_url);
6148 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6149 auth_challenge.end());
6150 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6151 origin, BoundNetLog());
6152 auth_handler->SetGenerateExpectation(
6153 test_config.proxy_auth_timing == AUTH_ASYNC,
6154 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156155 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6156 }
6157 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006158 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156159 std::string auth_challenge = "Mock realm=server";
6160 GURL origin(test_config.server_url);
6161 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6162 auth_challenge.end());
6163 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6164 origin, BoundNetLog());
6165 auth_handler->SetGenerateExpectation(
6166 test_config.server_auth_timing == AUTH_ASYNC,
6167 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156168 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6169 }
6170 if (test_config.proxy_url) {
6171 session_deps.proxy_service =
6172 CreateFixedProxyService(test_config.proxy_url);
6173 } else {
6174 session_deps.proxy_service = ProxyService::CreateNull();
6175 }
6176
6177 HttpRequestInfo request;
6178 request.method = "GET";
6179 request.url = GURL(test_config.server_url);
6180 request.load_flags = 0;
6181
6182 scoped_ptr<HttpTransaction> trans(
6183 new HttpNetworkTransaction(CreateSession(&session_deps)));
6184
6185 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6186 const TestRound& read_write_round = test_config.rounds[round];
6187
6188 // Set up expected reads and writes.
6189 MockRead reads[2];
6190 reads[0] = read_write_round.read;
6191 size_t length_reads = 1;
6192 if (read_write_round.extra_read) {
6193 reads[1] = *read_write_round.extra_read;
6194 length_reads = 2;
6195 }
6196
6197 MockWrite writes[2];
6198 writes[0] = read_write_round.write;
6199 size_t length_writes = 1;
6200 if (read_write_round.extra_write) {
6201 writes[1] = *read_write_round.extra_write;
6202 length_writes = 2;
6203 }
6204 StaticSocketDataProvider data_provider(
6205 reads, length_reads, writes, length_writes);
6206 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6207
6208 // Add an SSL sequence if necessary.
6209 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6210 if (round >= test_config.first_ssl_round)
6211 session_deps.socket_factory.AddSSLSocketDataProvider(
6212 &ssl_socket_data_provider);
6213
6214 // Start or restart the transaction.
6215 TestCompletionCallback callback;
6216 int rv;
6217 if (round == 0) {
6218 rv = trans->Start(&request, &callback, BoundNetLog());
6219 } else {
[email protected]13c8a092010-07-29 06:15:446220 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156221 }
6222 if (rv == ERR_IO_PENDING)
6223 rv = callback.WaitForResult();
6224
6225 // Compare results with expected data.
6226 EXPECT_EQ(read_write_round.expected_rv, rv);
6227 const HttpResponseInfo* response = trans->GetResponseInfo();
6228 if (read_write_round.expected_rv == OK) {
6229 EXPECT_FALSE(response == NULL);
6230 } else {
6231 EXPECT_TRUE(response == NULL);
6232 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6233 continue;
6234 }
6235 if (round + 1 < test_config.num_auth_rounds) {
6236 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6237 } else {
6238 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6239 }
6240 }
[email protected]e5ae96a2010-04-14 20:12:456241 }
[email protected]e60e47a2010-07-14 03:37:186242
6243 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
6244 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:456245}
6246
[email protected]c871bce92010-07-15 21:51:146247TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6248 // Do multi-round authentication and make sure it works correctly.
6249 SessionDependencies session_deps;
6250 HttpAuthHandlerMock::Factory* auth_factory(
6251 new HttpAuthHandlerMock::Factory());
6252 session_deps.http_auth_handler_factory.reset(auth_factory);
6253 session_deps.proxy_service = ProxyService::CreateNull();
6254 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6255 session_deps.host_resolver->set_synchronous_mode(true);
6256
6257 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6258 auth_handler->set_connection_based(true);
6259 std::string auth_challenge = "Mock realm=server";
6260 GURL origin("http://www.example.com");
6261 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6262 auth_challenge.end());
6263 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6264 origin, BoundNetLog());
6265 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6266
6267 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6268 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6269
6270 int rv = OK;
6271 const HttpResponseInfo* response = NULL;
6272 HttpRequestInfo request;
6273 request.method = "GET";
6274 request.url = origin;
6275 request.load_flags = 0;
6276 TestCompletionCallback callback;
6277
6278 const MockWrite kGet(
6279 "GET / HTTP/1.1\r\n"
6280 "Host: www.example.com\r\n"
6281 "Connection: keep-alive\r\n\r\n");
6282 const MockWrite kGetAuth(
6283 "GET / HTTP/1.1\r\n"
6284 "Host: www.example.com\r\n"
6285 "Connection: keep-alive\r\n"
6286 "Authorization: auth_token\r\n\r\n");
6287
6288 const MockRead kServerChallenge(
6289 "HTTP/1.1 401 Unauthorized\r\n"
6290 "WWW-Authenticate: Mock realm=server\r\n"
6291 "Content-Type: text/html; charset=iso-8859-1\r\n"
6292 "Content-Length: 14\r\n\r\n"
6293 "Unauthorized\r\n");
6294 const MockRead kSuccess(
6295 "HTTP/1.1 200 OK\r\n"
6296 "Content-Type: text/html; charset=iso-8859-1\r\n"
6297 "Content-Length: 3\r\n\r\n"
6298 "Yes");
6299
6300 MockWrite writes[] = {
6301 // First round
6302 kGet,
6303 // Second round
6304 kGetAuth,
6305 // Third round
6306 kGetAuth,
6307 };
6308 MockRead reads[] = {
6309 // First round
6310 kServerChallenge,
6311 // Second round
6312 kServerChallenge,
6313 // Third round
6314 kSuccess,
6315 };
6316 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6317 writes, arraysize(writes));
6318 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6319
6320 // First round
6321 auth_handler->SetGenerateExpectation(false, OK);
6322 rv = trans->Start(&request, &callback, BoundNetLog());
6323 if (rv == ERR_IO_PENDING)
6324 rv = callback.WaitForResult();
6325 EXPECT_EQ(OK, rv);
6326 response = trans->GetResponseInfo();
6327 ASSERT_FALSE(response == NULL);
6328 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6329
6330 // Second round
6331 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446332 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146333 if (rv == ERR_IO_PENDING)
6334 rv = callback.WaitForResult();
6335 EXPECT_EQ(OK, rv);
6336 response = trans->GetResponseInfo();
6337 ASSERT_FALSE(response == NULL);
6338 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6339
6340 // Third round
6341 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446342 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146343 if (rv == ERR_IO_PENDING)
6344 rv = callback.WaitForResult();
6345 EXPECT_EQ(OK, rv);
6346 response = trans->GetResponseInfo();
6347 ASSERT_FALSE(response == NULL);
6348 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6349}
6350
[email protected]aeaca1f2010-04-20 22:05:216351class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6352 public:
[email protected]06650c52010-06-03 00:49:176353 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216354 : fail_all_(fail_all) {
6355 }
6356
6357 virtual MockRead GetNextRead() {
6358 if (fail_all_)
6359 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6360
6361 return MockRead(false /* async */,
6362 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6363 }
6364
6365 virtual MockWriteResult OnWrite(const std::string& data) {
6366 return MockWriteResult(false /* async */, data.size());
6367 }
6368
6369 void Reset() {
6370 }
6371
6372 private:
6373 const bool fail_all_;
6374};
6375
6376// Test that we restart a connection when we see a decompression failure from
6377// the peer during the handshake. (In the real world we'll restart with SSLv3
6378// and we won't offer DEFLATE in that case.)
6379TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6380 HttpRequestInfo request;
6381 request.method = "GET";
6382 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6383 request.load_flags = 0;
6384
6385 SessionDependencies session_deps;
6386 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6387 false /* fail all reads */);
6388 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6389 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116390 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216391 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6392 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6393 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6394 session_deps.socket_factory.AddSSLSocketDataProvider(
6395 &ssl_socket_data_provider1);
6396 session_deps.socket_factory.AddSSLSocketDataProvider(
6397 &ssl_socket_data_provider2);
6398
[email protected]e60e47a2010-07-14 03:37:186399 // Work around http://crbug.com/37454
6400 StaticSocketDataProvider bug37454_connection;
6401 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6402 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6403
[email protected]aeaca1f2010-04-20 22:05:216404 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6405 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6406 TestCompletionCallback callback;
6407
[email protected]5a1d7ca2010-04-28 20:12:276408 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216409 EXPECT_EQ(ERR_IO_PENDING, rv);
6410 EXPECT_EQ(OK, callback.WaitForResult());
6411
6412 const HttpResponseInfo* response = trans->GetResponseInfo();
6413 ASSERT_TRUE(response != NULL);
6414 ASSERT_TRUE(response->headers != NULL);
6415 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6416
6417 std::string response_data;
6418 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6419 EXPECT_EQ("ok.", response_data);
6420}
6421
6422// Test that we restart a connection if we get a decompression failure from the
6423// peer while reading the first bytes from the connection. This occurs when the
6424// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6425// in the handshake.
6426TEST_F(HttpNetworkTransactionTest,
6427 RestartAfterTLSDecompressionFailureWithFalseStart) {
6428 HttpRequestInfo request;
6429 request.method = "GET";
6430 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6431 request.load_flags = 0;
6432
6433 SessionDependencies session_deps;
6434 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6435 true /* fail all reads */);
6436 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6437 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6438 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6439 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6440 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6441 session_deps.socket_factory.AddSSLSocketDataProvider(
6442 &ssl_socket_data_provider1);
6443 session_deps.socket_factory.AddSSLSocketDataProvider(
6444 &ssl_socket_data_provider2);
6445
6446 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6447 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6448 TestCompletionCallback callback;
6449
[email protected]5a1d7ca2010-04-28 20:12:276450 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216451 EXPECT_EQ(ERR_IO_PENDING, rv);
6452 EXPECT_EQ(OK, callback.WaitForResult());
6453
6454 const HttpResponseInfo* response = trans->GetResponseInfo();
6455 ASSERT_TRUE(response != NULL);
6456 ASSERT_TRUE(response->headers != NULL);
6457 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6458
6459 std::string response_data;
6460 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6461 EXPECT_EQ("ok.", response_data);
6462}
6463
[email protected]65041fa2010-05-21 06:56:536464// This tests the case that a request is issued via http instead of spdy after
6465// npn is negotiated.
6466TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:386467 HttpStreamFactory::set_use_alternate_protocols(true);
6468 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:536469 SessionDependencies session_deps;
6470 HttpRequestInfo request;
6471 request.method = "GET";
6472 request.url = GURL("https://www.google.com/");
6473 request.load_flags = 0;
6474
6475 MockWrite data_writes[] = {
6476 MockWrite("GET / HTTP/1.1\r\n"
6477 "Host: www.google.com\r\n"
6478 "Connection: keep-alive\r\n\r\n"),
6479 };
6480
6481 MockRead data_reads[] = {
6482 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356483 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536484 MockRead("hello world"),
6485 MockRead(false, OK),
6486 };
6487
6488 SSLSocketDataProvider ssl(true, OK);
6489 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6490 ssl.next_proto = "http/1.1";
6491
6492 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6493
6494 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6495 data_writes, arraysize(data_writes));
6496 session_deps.socket_factory.AddSocketDataProvider(&data);
6497
6498 TestCompletionCallback callback;
6499
6500 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6501 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6502
6503 int rv = trans->Start(&request, &callback, BoundNetLog());
6504
6505 EXPECT_EQ(ERR_IO_PENDING, rv);
6506 EXPECT_EQ(OK, callback.WaitForResult());
6507
6508 const HttpResponseInfo* response = trans->GetResponseInfo();
6509 ASSERT_TRUE(response != NULL);
6510 ASSERT_TRUE(response->headers != NULL);
6511 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6512
6513 std::string response_data;
6514 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6515 EXPECT_EQ("hello world", response_data);
6516
6517 EXPECT_FALSE(response->was_fetched_via_spdy);
6518 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576519 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536520
[email protected]8e6441ca2010-08-19 05:56:386521 HttpStreamFactory::set_next_protos("");
6522 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:536523}
[email protected]26ef6582010-06-24 02:30:476524
6525TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6526 // Simulate the SSL handshake completing with an NPN negotiation
6527 // followed by an immediate server closing of the socket.
6528 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:386529 HttpStreamFactory::set_use_alternate_protocols(true);
6530 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476531 SessionDependencies session_deps;
6532
6533 HttpRequestInfo request;
6534 request.method = "GET";
6535 request.url = GURL("https://www.google.com/");
6536 request.load_flags = 0;
6537
6538 SSLSocketDataProvider ssl(true, OK);
6539 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356540 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476541 ssl.was_npn_negotiated = true;
6542 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6543
[email protected]2bd93022010-07-17 00:58:446544 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136545 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476546
6547 MockRead spdy_reads[] = {
6548 MockRead(false, 0, 0) // Not async - return 0 immediately.
6549 };
6550
6551 scoped_refptr<DelayedSocketData> spdy_data(
6552 new DelayedSocketData(
6553 0, // don't wait in this case, immediate hangup.
6554 spdy_reads, arraysize(spdy_reads),
6555 spdy_writes, arraysize(spdy_writes)));
6556 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6557
6558 TestCompletionCallback callback;
6559
6560 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6561 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6562
6563 int rv = trans->Start(&request, &callback, BoundNetLog());
6564 EXPECT_EQ(ERR_IO_PENDING, rv);
6565 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6566
[email protected]8e6441ca2010-08-19 05:56:386567 HttpStreamFactory::set_next_protos("");
6568 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:476569}
[email protected]65d34382010-07-01 18:12:266570
[email protected]f45c1ee2010-08-03 00:54:306571TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
6572 // This test ensures that the URL passed into the proxy is upgraded
6573 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:386574 HttpStreamFactory::set_use_alternate_protocols(true);
6575 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:306576 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
6577
6578 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6579 HttpAuthHandlerMock::Factory* auth_factory =
6580 new HttpAuthHandlerMock::Factory();
6581 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
6582 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6583 auth_factory->set_do_init_from_challenge(true);
6584 session_deps.http_auth_handler_factory.reset(auth_factory);
6585
6586 HttpRequestInfo request;
6587 request.method = "GET";
6588 request.url = GURL("http://www.google.com");
6589 request.load_flags = 0;
6590
6591 // First round goes unauthenticated through the proxy.
6592 MockWrite data_writes_1[] = {
6593 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6594 "Host: www.google.com\r\n"
6595 "Proxy-Connection: keep-alive\r\n"
6596 "\r\n"),
6597 };
6598 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:596599 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:306600 MockRead("HTTP/1.1 200 OK\r\n"
6601 "Alternate-Protocol: 443:npn-spdy/2\r\n"
6602 "Proxy-Connection: close\r\n"
6603 "\r\n"),
6604 };
6605 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
6606 data_writes_1, arraysize(data_writes_1));
6607
6608 // Second round tries to tunnel to www.google.com due to the
6609 // Alternate-Protocol announcement in the first round. It fails due
6610 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:596611 // After the failure, a tunnel is established to www.google.com using
6612 // Proxy-Authorization headers. There is then a SPDY request round.
6613 //
6614 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
6615 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
6616 // does a Disconnect and Connect on the same socket, rather than trying
6617 // to obtain a new one.
6618 //
6619 // NOTE: Originally, the proxy response to the second CONNECT request
6620 // simply returned another 407 so the unit test could skip the SSL connection
6621 // establishment and SPDY framing issues. Alas, the
6622 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:306623 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:596624
[email protected]f45c1ee2010-08-03 00:54:306625 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6626 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6627 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6628
[email protected]394816e92010-08-03 07:38:596629 MockWrite data_writes_2[] = {
6630 // First connection attempt without Proxy-Authorization.
6631 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6632 "Host: www.google.com\r\n"
6633 "Proxy-Connection: keep-alive\r\n"
6634 "\r\n"),
6635
6636 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:306637 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6638 "Host: www.google.com\r\n"
6639 "Proxy-Connection: keep-alive\r\n"
6640 "Proxy-Authorization: auth_token\r\n"
6641 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:306642
[email protected]394816e92010-08-03 07:38:596643 // SPDY request
6644 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:306645 };
[email protected]394816e92010-08-03 07:38:596646 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
6647 "Proxy-Authenticate: Mock\r\n"
6648 "Proxy-Connection: close\r\n"
6649 "\r\n");
6650 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6651 MockRead data_reads_2[] = {
6652 // First connection attempt fails
6653 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
6654 MockRead(true, kRejectConnectResponse,
6655 arraysize(kRejectConnectResponse) - 1, 1),
6656
6657 // Second connection attempt passes
6658 MockRead(true, kAcceptConnectResponse,
6659 arraysize(kAcceptConnectResponse) -1, 4),
6660
6661 // SPDY response
6662 CreateMockRead(*resp.get(), 6),
6663 CreateMockRead(*data.get(), 6),
6664 MockRead(true, 0, 0, 6),
6665 };
6666 scoped_refptr<OrderedSocketData> data_2(
6667 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
6668 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:306669
6670 SSLSocketDataProvider ssl(true, OK);
6671 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6672 ssl.next_proto = "spdy/2";
6673 ssl.was_npn_negotiated = true;
6674
6675 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:596676 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:306677 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6678 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6679
6680 // First round should work and provide the Alternate-Protocol state.
6681 TestCompletionCallback callback_1;
6682 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
6683 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
6684 EXPECT_EQ(ERR_IO_PENDING, rv);
6685 EXPECT_EQ(OK, callback_1.WaitForResult());
6686
6687 // Second round should attempt a tunnel connect and get an auth challenge.
6688 TestCompletionCallback callback_2;
6689 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
6690 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
6691 EXPECT_EQ(ERR_IO_PENDING, rv);
6692 EXPECT_EQ(OK, callback_2.WaitForResult());
6693 const HttpResponseInfo* response = trans_2->GetResponseInfo();
6694 ASSERT_FALSE(response == NULL);
6695 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6696
6697 // Restart with auth. Tunnel should work and response received.
6698 TestCompletionCallback callback_3;
6699 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
6700 EXPECT_EQ(ERR_IO_PENDING, rv);
6701 EXPECT_EQ(OK, callback_3.WaitForResult());
6702
6703 // After all that work, these two lines (or actually, just the scheme) are
6704 // what this test is all about. Make sure it happens correctly.
6705 const GURL& request_url = auth_handler->request_url();
6706 EXPECT_EQ("https", request_url.scheme());
6707 EXPECT_EQ("www.google.com", request_url.host());
6708
[email protected]8e6441ca2010-08-19 05:56:386709 HttpStreamFactory::set_next_protos("");
6710 HttpStreamFactory::set_use_alternate_protocols(false);
6711}
6712
6713// Test that if we cancel the transaction as the connection is completing, that
6714// everything tears down correctly.
6715TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
6716 // Setup everything about the connection to complete synchronously, so that
6717 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
6718 // for is the callback from the HttpStreamRequest.
6719 // Then cancel the transaction.
6720 // Verify that we don't crash.
6721 MockConnect mock_connect(false, OK);
6722 MockRead data_reads[] = {
6723 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
6724 MockRead(false, "hello world"),
6725 MockRead(false, OK),
6726 };
6727
6728 SessionDependencies session_deps;
6729 session_deps.host_resolver->set_synchronous_mode(true);
6730 scoped_ptr<HttpTransaction> trans(
6731 new HttpNetworkTransaction(CreateSession(&session_deps)));
6732
6733 HttpRequestInfo request;
6734 request.method = "GET";
6735 request.url = GURL("http://www.google.com/");
6736 request.load_flags = 0;
6737
6738 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6739 data.set_connect_data(mock_connect);
6740 session_deps.socket_factory.AddSocketDataProvider(&data);
6741
6742 TestCompletionCallback callback;
6743
6744 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
6745 int rv = trans->Start(&request, &callback, log.bound());
6746 EXPECT_EQ(ERR_IO_PENDING, rv);
6747 trans.reset(); // Cancel the transaction here.
6748
6749 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:306750}
6751
[email protected]76a505b2010-08-25 06:23:006752// Test a basic GET request through a proxy.
6753TEST_F(HttpNetworkTransactionTest, ProxyGet) {
6754 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6755 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
6756 session_deps.net_log = log.bound().net_log();
6757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6758
6759 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6760
6761 HttpRequestInfo request;
6762 request.method = "GET";
6763 request.url = GURL("http://www.google.com/");
6764
6765 MockWrite data_writes1[] = {
6766 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6767 "Host: www.google.com\r\n"
6768 "Proxy-Connection: keep-alive\r\n\r\n"),
6769 };
6770
6771 MockRead data_reads1[] = {
6772 MockRead("HTTP/1.1 200 OK\r\n"),
6773 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6774 MockRead("Content-Length: 100\r\n\r\n"),
6775 MockRead(false, OK),
6776 };
6777
6778 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6779 data_writes1, arraysize(data_writes1));
6780 session_deps.socket_factory.AddSocketDataProvider(&data1);
6781
6782 TestCompletionCallback callback1;
6783
6784 int rv = trans->Start(&request, &callback1, log.bound());
6785 EXPECT_EQ(ERR_IO_PENDING, rv);
6786
6787 rv = callback1.WaitForResult();
6788 EXPECT_EQ(OK, rv);
6789
6790 const HttpResponseInfo* response = trans->GetResponseInfo();
6791 ASSERT_FALSE(response == NULL);
6792
6793 EXPECT_TRUE(response->headers->IsKeepAlive());
6794 EXPECT_EQ(200, response->headers->response_code());
6795 EXPECT_EQ(100, response->headers->GetContentLength());
6796 EXPECT_TRUE(response->was_fetched_via_proxy);
6797 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6798}
6799
6800// Test a basic HTTPS GET request through a proxy.
6801TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
6802 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6803 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
6804 session_deps.net_log = log.bound().net_log();
6805 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6806
6807 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6808
6809 HttpRequestInfo request;
6810 request.method = "GET";
6811 request.url = GURL("https://www.google.com/");
6812
6813 // Since we have proxy, should try to establish tunnel.
6814 MockWrite data_writes1[] = {
6815 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6816 "Host: www.google.com\r\n"
6817 "Proxy-Connection: keep-alive\r\n\r\n"),
6818
6819 MockWrite("GET / HTTP/1.1\r\n"
6820 "Host: www.google.com\r\n"
6821 "Connection: keep-alive\r\n\r\n"),
6822 };
6823
6824 MockRead data_reads1[] = {
6825 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6826
6827 MockRead("HTTP/1.1 200 OK\r\n"),
6828 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6829 MockRead("Content-Length: 100\r\n\r\n"),
6830 MockRead(false, OK),
6831 };
6832
6833 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6834 data_writes1, arraysize(data_writes1));
6835 session_deps.socket_factory.AddSocketDataProvider(&data1);
6836 SSLSocketDataProvider ssl(true, OK);
6837 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6838
6839 TestCompletionCallback callback1;
6840
6841 int rv = trans->Start(&request, &callback1, log.bound());
6842 EXPECT_EQ(ERR_IO_PENDING, rv);
6843
6844 rv = callback1.WaitForResult();
6845 EXPECT_EQ(OK, rv);
6846 size_t pos = ExpectLogContainsSomewhere(
6847 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6848 NetLog::PHASE_NONE);
6849 ExpectLogContainsSomewhere(
6850 log.entries(), pos,
6851 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6852 NetLog::PHASE_NONE);
6853
6854 const HttpResponseInfo* response = trans->GetResponseInfo();
6855 ASSERT_FALSE(response == NULL);
6856
6857 EXPECT_TRUE(response->headers->IsKeepAlive());
6858 EXPECT_EQ(200, response->headers->response_code());
6859 EXPECT_EQ(100, response->headers->GetContentLength());
6860 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
6861 EXPECT_TRUE(response->was_fetched_via_proxy);
6862}
6863
6864// Test a basic HTTPS GET request through a proxy, but the server hangs up
6865// while establishing the tunnel.
6866TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
6867 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6868 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
6869 session_deps.net_log = log.bound().net_log();
6870 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6871
6872 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6873
6874 HttpRequestInfo request;
6875 request.method = "GET";
6876 request.url = GURL("https://www.google.com/");
6877
6878 // Since we have proxy, should try to establish tunnel.
6879 MockWrite data_writes1[] = {
6880 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6881 "Host: www.google.com\r\n"
6882 "Proxy-Connection: keep-alive\r\n\r\n"),
6883
6884 MockWrite("GET / HTTP/1.1\r\n"
6885 "Host: www.google.com\r\n"
6886 "Connection: keep-alive\r\n\r\n"),
6887 };
6888
6889 MockRead data_reads1[] = {
6890 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
6891 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
6892 MockRead(true, 0, 0), // EOF
6893 };
6894
6895 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6896 data_writes1, arraysize(data_writes1));
6897 session_deps.socket_factory.AddSocketDataProvider(&data1);
6898 SSLSocketDataProvider ssl(true, OK);
6899 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6900
6901 TestCompletionCallback callback1;
6902
6903 int rv = trans->Start(&request, &callback1, log.bound());
6904 EXPECT_EQ(ERR_IO_PENDING, rv);
6905
6906 rv = callback1.WaitForResult();
6907 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
6908 size_t pos = ExpectLogContainsSomewhere(
6909 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
6910 NetLog::PHASE_NONE);
6911 ExpectLogContainsSomewhere(
6912 log.entries(), pos,
6913 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
6914 NetLog::PHASE_NONE);
6915}
6916
[email protected]89ceba9a2009-03-21 03:46:066917} // namespace net