blob: 5d21eba3050277bcdae8b6656ea9aa60bcf6f523 [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<>
[email protected]2df19bb2010-08-25 20:13:46330CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
331 HttpNetworkSession* session)
332 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
333 NULL, NULL) {}
334
335template<>
[email protected]e60e47a2010-07-14 03:37:18336CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
337 HttpNetworkSession* session)
338 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
339 NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11340
[email protected]231d5a32008-09-13 00:45:27341//-----------------------------------------------------------------------------
342
[email protected]dae22c52010-07-30 02:16:35343// This is the expected list of advertised protocols from the browser's NPN
344// list.
345static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
346
347// This is the expected return from a current server advertising SPDY.
348static const char kAlternateProtocolHttpHeader[] =
349 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
350
[email protected]231d5a32008-09-13 00:45:27351TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59352 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40353 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43354 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27355}
356
357TEST_F(HttpNetworkTransactionTest, SimpleGET) {
358 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35359 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
360 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42361 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27362 };
[email protected]31a2bfe2010-02-09 08:03:39363 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
364 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42365 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27366 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
367 EXPECT_EQ("hello world", out.response_data);
368}
369
370// Response with no status line.
371TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
372 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35373 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42374 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27375 };
[email protected]31a2bfe2010-02-09 08:03:39376 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
377 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42378 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27379 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
380 EXPECT_EQ("hello world", out.response_data);
381}
382
383// Allow up to 4 bytes of junk to precede status line.
384TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
385 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35386 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42387 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27388 };
[email protected]31a2bfe2010-02-09 08:03:39389 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
390 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42391 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27392 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
393 EXPECT_EQ("DATA", out.response_data);
394}
395
396// Allow up to 4 bytes of junk to precede status line.
397TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
398 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35399 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42400 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27401 };
[email protected]31a2bfe2010-02-09 08:03:39402 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
403 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42404 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27405 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
406 EXPECT_EQ("DATA", out.response_data);
407}
408
409// Beyond 4 bytes of slop and it should fail to find a status line.
410TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
411 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35412 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42413 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27414 };
[email protected]31a2bfe2010-02-09 08:03:39415 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
416 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42417 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25418 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
419 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27420}
421
422// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
423TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
424 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35425 MockRead("\n"),
426 MockRead("\n"),
427 MockRead("Q"),
428 MockRead("J"),
429 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42430 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27431 };
[email protected]31a2bfe2010-02-09 08:03:39432 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
433 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42434 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27435 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
436 EXPECT_EQ("DATA", out.response_data);
437}
438
439// Close the connection before enough bytes to have a status line.
440TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
441 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35442 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42443 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27444 };
[email protected]31a2bfe2010-02-09 08:03:39445 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
446 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42447 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27448 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
449 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52450}
451
[email protected]f9d44aa2008-09-23 23:57:17452// Simulate a 204 response, lacking a Content-Length header, sent over a
453// persistent connection. The response should still terminate since a 204
454// cannot have a response body.
455TEST_F(HttpNetworkTransactionTest, StopsReading204) {
456 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35457 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
458 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42459 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17460 };
[email protected]31a2bfe2010-02-09 08:03:39461 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
462 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42463 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17464 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
465 EXPECT_EQ("", out.response_data);
466}
467
[email protected]0877e3d2009-10-17 22:29:57468// A simple request using chunked encoding with some extra data after.
469// (Like might be seen in a pipelined response.)
470TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
471 MockRead data_reads[] = {
472 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
473 MockRead("5\r\nHello\r\n"),
474 MockRead("1\r\n"),
475 MockRead(" \r\n"),
476 MockRead("5\r\nworld\r\n"),
477 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
478 MockRead(false, OK),
479 };
[email protected]31a2bfe2010-02-09 08:03:39480 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
481 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57482 EXPECT_EQ(OK, out.rv);
483 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
484 EXPECT_EQ("Hello world", out.response_data);
485}
486
[email protected]ef0faf2e72009-03-05 23:27:23487// Do a request using the HEAD method. Verify that we don't try to read the
488// message body (since HEAD has none).
489TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59490 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40491 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43492 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23493
[email protected]1c773ea12009-04-28 19:58:42494 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23495 request.method = "HEAD";
496 request.url = GURL("http://www.google.com/");
497 request.load_flags = 0;
498
499 MockWrite data_writes1[] = {
500 MockWrite("HEAD / HTTP/1.1\r\n"
501 "Host: www.google.com\r\n"
502 "Connection: keep-alive\r\n"
503 "Content-Length: 0\r\n\r\n"),
504 };
505 MockRead data_reads1[] = {
506 MockRead("HTTP/1.1 404 Not Found\r\n"),
507 MockRead("Server: Blah\r\n"),
508 MockRead("Content-Length: 1234\r\n\r\n"),
509
510 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42511 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23512 };
513
[email protected]31a2bfe2010-02-09 08:03:39514 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
515 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59516 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23517
518 TestCompletionCallback callback1;
519
[email protected]5a1d7ca2010-04-28 20:12:27520 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42521 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23522
523 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42524 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23525
[email protected]1c773ea12009-04-28 19:58:42526 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23527 EXPECT_FALSE(response == NULL);
528
529 // Check that the headers got parsed.
530 EXPECT_TRUE(response->headers != NULL);
531 EXPECT_EQ(1234, response->headers->GetContentLength());
532 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
533
534 std::string server_header;
535 void* iter = NULL;
536 bool has_server_header = response->headers->EnumerateHeader(
537 &iter, "Server", &server_header);
538 EXPECT_TRUE(has_server_header);
539 EXPECT_EQ("Blah", server_header);
540
541 // Reading should give EOF right away, since there is no message body
542 // (despite non-zero content-length).
543 std::string response_data;
544 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42545 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23546 EXPECT_EQ("", response_data);
547}
548
initial.commit586acc5fe2008-07-26 22:42:52549TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59550 SessionDependencies session_deps;
551 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52552
553 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35554 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
555 MockRead("hello"),
556 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
557 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42558 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52559 };
[email protected]31a2bfe2010-02-09 08:03:39560 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59561 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52562
563 const char* kExpectedResponseData[] = {
564 "hello", "world"
565 };
566
567 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43568 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52569
[email protected]1c773ea12009-04-28 19:58:42570 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52571 request.method = "GET";
572 request.url = GURL("http://www.google.com/");
573 request.load_flags = 0;
574
575 TestCompletionCallback callback;
576
[email protected]5a1d7ca2010-04-28 20:12:27577 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42578 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52579
580 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42581 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52582
[email protected]1c773ea12009-04-28 19:58:42583 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52584 EXPECT_TRUE(response != NULL);
585
586 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25587 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52588
589 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57590 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42591 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25592 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52593 }
594}
595
596TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59597 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40598 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43599 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52600
[email protected]1c773ea12009-04-28 19:58:42601 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52602 request.method = "POST";
603 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42604 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52605 request.upload_data->AppendBytes("foo", 3);
606 request.load_flags = 0;
607
608 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35609 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
610 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
611 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42612 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52613 };
[email protected]31a2bfe2010-02-09 08:03:39614 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59615 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52616
617 TestCompletionCallback callback;
618
[email protected]5a1d7ca2010-04-28 20:12:27619 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42620 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52621
622 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42623 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52624
[email protected]1c773ea12009-04-28 19:58:42625 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52626 EXPECT_TRUE(response != NULL);
627
628 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25629 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52630
631 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57632 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42633 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25634 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52635}
636
[email protected]3a2d3662009-03-27 03:49:14637// This test is almost the same as Ignores100 above, but the response contains
638// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57639// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14640TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59641 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40642 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43643 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14644
[email protected]1c773ea12009-04-28 19:58:42645 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14646 request.method = "GET";
647 request.url = GURL("http://www.foo.com/");
648 request.load_flags = 0;
649
650 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57651 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
652 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14653 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42654 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14655 };
[email protected]31a2bfe2010-02-09 08:03:39656 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59657 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14658
659 TestCompletionCallback callback;
660
[email protected]5a1d7ca2010-04-28 20:12:27661 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42662 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14663
664 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42665 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14666
[email protected]1c773ea12009-04-28 19:58:42667 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14668 EXPECT_TRUE(response != NULL);
669
670 EXPECT_TRUE(response->headers != NULL);
671 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
672
673 std::string response_data;
674 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42675 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14676 EXPECT_EQ("hello world", response_data);
677}
678
[email protected]ee9410e72010-01-07 01:42:38679TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
680 SessionDependencies session_deps;
681 scoped_ptr<HttpTransaction> trans(
682 new HttpNetworkTransaction(CreateSession(&session_deps)));
683
684 HttpRequestInfo request;
685 request.method = "POST";
686 request.url = GURL("http://www.foo.com/");
687 request.load_flags = 0;
688
689 MockRead data_reads[] = {
690 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
691 MockRead(true, 0),
692 };
[email protected]31a2bfe2010-02-09 08:03:39693 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38694 session_deps.socket_factory.AddSocketDataProvider(&data);
695
696 TestCompletionCallback callback;
697
[email protected]5a1d7ca2010-04-28 20:12:27698 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38699 EXPECT_EQ(ERR_IO_PENDING, rv);
700
701 rv = callback.WaitForResult();
702 EXPECT_EQ(OK, rv);
703
704 std::string response_data;
705 rv = ReadTransaction(trans.get(), &response_data);
706 EXPECT_EQ(OK, rv);
707 EXPECT_EQ("", response_data);
708}
709
710TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
711 SessionDependencies session_deps;
712 scoped_ptr<HttpTransaction> trans(
713 new HttpNetworkTransaction(CreateSession(&session_deps)));
714
715 HttpRequestInfo request;
716 request.method = "POST";
717 request.url = GURL("http://www.foo.com/");
718 request.load_flags = 0;
719
720 MockRead data_reads[] = {
721 MockRead(true, 0),
722 };
[email protected]31a2bfe2010-02-09 08:03:39723 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38724 session_deps.socket_factory.AddSocketDataProvider(&data);
725
726 TestCompletionCallback callback;
727
[email protected]5a1d7ca2010-04-28 20:12:27728 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38729 EXPECT_EQ(ERR_IO_PENDING, rv);
730
731 rv = callback.WaitForResult();
732 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
733}
734
[email protected]3d2a59b2008-09-26 19:44:25735// read_failure specifies a read failure that should cause the network
736// transaction to resend the request.
737void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
738 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59739 SessionDependencies session_deps;
740 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52741
[email protected]1c773ea12009-04-28 19:58:42742 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52743 request.method = "GET";
744 request.url = GURL("http://www.foo.com/");
745 request.load_flags = 0;
746
747 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35748 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
749 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25750 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52751 };
[email protected]31a2bfe2010-02-09 08:03:39752 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59753 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52754
755 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35756 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
757 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42758 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52759 };
[email protected]31a2bfe2010-02-09 08:03:39760 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59761 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52762
763 const char* kExpectedResponseData[] = {
764 "hello", "world"
765 };
766
767 for (int i = 0; i < 2; ++i) {
768 TestCompletionCallback callback;
769
[email protected]5695b8c2009-09-30 21:36:43770 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52771
[email protected]5a1d7ca2010-04-28 20:12:27772 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42773 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52774
775 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42776 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52777
[email protected]1c773ea12009-04-28 19:58:42778 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52779 EXPECT_TRUE(response != NULL);
780
781 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25782 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52783
784 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57785 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42786 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25787 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52788 }
789}
[email protected]3d2a59b2008-09-26 19:44:25790
791TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42792 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25793 KeepAliveConnectionResendRequestTest(read_failure);
794}
795
796TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42797 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25798 KeepAliveConnectionResendRequestTest(read_failure);
799}
800
801TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59802 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40803 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43804 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25805
[email protected]1c773ea12009-04-28 19:58:42806 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25807 request.method = "GET";
808 request.url = GURL("http://www.google.com/");
809 request.load_flags = 0;
810
811 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42812 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35813 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
814 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42815 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25816 };
[email protected]31a2bfe2010-02-09 08:03:39817 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59818 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25819
820 TestCompletionCallback callback;
821
[email protected]5a1d7ca2010-04-28 20:12:27822 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42823 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25824
825 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42826 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25827
[email protected]1c773ea12009-04-28 19:58:42828 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25829 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25830}
831
832// What do various browsers do when the server closes a non-keepalive
833// connection without sending any response header or body?
834//
835// IE7: error page
836// Safari 3.1.2 (Windows): error page
837// Firefox 3.0.1: blank page
838// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42839// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
840// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25841TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
842 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42843 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35844 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
845 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42846 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25847 };
[email protected]31a2bfe2010-02-09 08:03:39848 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
849 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42850 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25851}
[email protected]038e9a32008-10-08 22:40:16852
[email protected]fc31d6a42010-06-24 18:05:13853// Test that we correctly reuse a keep-alive connection after receiving a 304.
854TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
855 SessionDependencies session_deps;
856 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
857
858 HttpRequestInfo request;
859 request.method = "GET";
860 request.url = GURL("http://www.foo.com/");
861 request.load_flags = 0;
862
863 MockRead data1_reads[] = {
864 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
865 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
866 MockRead("hello"),
867 };
868 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
869 session_deps.socket_factory.AddSocketDataProvider(&data1);
870
871 MockRead data2_reads[] = {
872 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
873 };
874 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
875 session_deps.socket_factory.AddSocketDataProvider(&data2);
876
877 for (int i = 0; i < 2; ++i) {
878 TestCompletionCallback callback;
879
880 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
881
882 int rv = trans->Start(&request, &callback, BoundNetLog());
883 EXPECT_EQ(ERR_IO_PENDING, rv);
884
885 rv = callback.WaitForResult();
886 EXPECT_EQ(OK, rv);
887
888 const HttpResponseInfo* response = trans->GetResponseInfo();
889 EXPECT_TRUE(response != NULL);
890
891 EXPECT_TRUE(response->headers != NULL);
892 if (i == 0) {
893 EXPECT_EQ("HTTP/1.1 304 Not Modified",
894 response->headers->GetStatusLine());
895 // We intentionally don't read the response in this case, to reflect how
896 // HttpCache::Transaction uses HttpNetworkTransaction.
897 } else {
898 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
899 std::string response_data;
900 rv = ReadTransaction(trans.get(), &response_data);
901 EXPECT_EQ(OK, rv);
902 EXPECT_EQ("hello", response_data);
903 }
904 }
905}
906
[email protected]038e9a32008-10-08 22:40:16907// Test the request-challenge-retry sequence for basic auth.
908// (basic auth is the easiest to mock, because it has no randomness).
909TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59910 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40911 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43912 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16913
[email protected]1c773ea12009-04-28 19:58:42914 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16915 request.method = "GET";
916 request.url = GURL("http://www.google.com/");
917 request.load_flags = 0;
918
[email protected]f9ee6b52008-11-08 06:46:23919 MockWrite data_writes1[] = {
920 MockWrite("GET / HTTP/1.1\r\n"
921 "Host: www.google.com\r\n"
922 "Connection: keep-alive\r\n\r\n"),
923 };
924
[email protected]038e9a32008-10-08 22:40:16925 MockRead data_reads1[] = {
926 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
927 // Give a couple authenticate options (only the middle one is actually
928 // supported).
[email protected]22927ad2009-09-21 19:56:19929 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16930 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
931 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
932 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
933 // Large content-length -- won't matter, as connection will be reset.
934 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42935 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16936 };
937
938 // After calling trans->RestartWithAuth(), this is the request we should
939 // be issuing -- the final header line contains the credentials.
940 MockWrite data_writes2[] = {
941 MockWrite("GET / HTTP/1.1\r\n"
942 "Host: www.google.com\r\n"
943 "Connection: keep-alive\r\n"
944 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
945 };
946
947 // Lastly, the server responds with the actual content.
948 MockRead data_reads2[] = {
949 MockRead("HTTP/1.0 200 OK\r\n"),
950 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
951 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42952 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16953 };
954
[email protected]31a2bfe2010-02-09 08:03:39955 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
956 data_writes1, arraysize(data_writes1));
957 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
958 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59959 session_deps.socket_factory.AddSocketDataProvider(&data1);
960 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16961
962 TestCompletionCallback callback1;
963
[email protected]5a1d7ca2010-04-28 20:12:27964 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42965 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16966
967 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42968 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16969
[email protected]1c773ea12009-04-28 19:58:42970 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16971 EXPECT_FALSE(response == NULL);
972
973 // The password prompt info should have been set in response->auth_challenge.
974 EXPECT_FALSE(response->auth_challenge.get() == NULL);
975
[email protected]71e4573a2009-05-21 22:03:00976 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16977 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
978 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
979
980 TestCompletionCallback callback2;
981
[email protected]13c8a092010-07-29 06:15:44982 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:42983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16984
985 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42986 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16987
988 response = trans->GetResponseInfo();
989 EXPECT_FALSE(response == NULL);
990 EXPECT_TRUE(response->auth_challenge.get() == NULL);
991 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16992}
993
[email protected]861fcd52009-08-26 02:33:46994TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
995 SessionDependencies session_deps;
996 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43997 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46998
999 HttpRequestInfo request;
1000 request.method = "GET";
1001 request.url = GURL("http://www.google.com/");
1002 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1003
1004 MockWrite data_writes[] = {
1005 MockWrite("GET / HTTP/1.1\r\n"
1006 "Host: www.google.com\r\n"
1007 "Connection: keep-alive\r\n\r\n"),
1008 };
1009
1010 MockRead data_reads[] = {
1011 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1012 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1013 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1014 // Large content-length -- won't matter, as connection will be reset.
1015 MockRead("Content-Length: 10000\r\n\r\n"),
1016 MockRead(false, ERR_FAILED),
1017 };
1018
[email protected]31a2bfe2010-02-09 08:03:391019 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1020 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591021 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461022 TestCompletionCallback callback;
1023
[email protected]5a1d7ca2010-04-28 20:12:271024 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461025 EXPECT_EQ(ERR_IO_PENDING, rv);
1026
1027 rv = callback.WaitForResult();
1028 EXPECT_EQ(0, rv);
1029
1030 const HttpResponseInfo* response = trans->GetResponseInfo();
1031 ASSERT_FALSE(response == NULL);
1032 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1033}
1034
[email protected]2d2697f92009-02-18 21:00:321035// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1036// connection.
1037TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591038 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401039 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431040 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321041
[email protected]1c773ea12009-04-28 19:58:421042 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321043 request.method = "GET";
1044 request.url = GURL("http://www.google.com/");
1045 request.load_flags = 0;
1046
1047 MockWrite data_writes1[] = {
1048 MockWrite("GET / HTTP/1.1\r\n"
1049 "Host: www.google.com\r\n"
1050 "Connection: keep-alive\r\n\r\n"),
1051
1052 // After calling trans->RestartWithAuth(), this is the request we should
1053 // be issuing -- the final header line contains the credentials.
1054 MockWrite("GET / HTTP/1.1\r\n"
1055 "Host: www.google.com\r\n"
1056 "Connection: keep-alive\r\n"
1057 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1058 };
1059
1060 MockRead data_reads1[] = {
1061 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1062 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1063 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1064 MockRead("Content-Length: 14\r\n\r\n"),
1065 MockRead("Unauthorized\r\n"),
1066
1067 // Lastly, the server responds with the actual content.
1068 MockRead("HTTP/1.1 200 OK\r\n"),
1069 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1070 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421071 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321072 };
1073
[email protected]31a2bfe2010-02-09 08:03:391074 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1075 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591076 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321077
1078 TestCompletionCallback callback1;
1079
[email protected]5a1d7ca2010-04-28 20:12:271080 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421081 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321082
1083 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421084 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321085
[email protected]1c773ea12009-04-28 19:58:421086 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321087 EXPECT_FALSE(response == NULL);
1088
1089 // The password prompt info should have been set in response->auth_challenge.
1090 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1091
[email protected]71e4573a2009-05-21 22:03:001092 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321093 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1094 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1095
1096 TestCompletionCallback callback2;
1097
[email protected]13c8a092010-07-29 06:15:441098 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421099 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321100
1101 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421102 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321103
1104 response = trans->GetResponseInfo();
1105 EXPECT_FALSE(response == NULL);
1106 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1107 EXPECT_EQ(100, response->headers->GetContentLength());
1108}
1109
1110// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1111// connection and with no response body to drain.
1112TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591113 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401114 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431115 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321116
[email protected]1c773ea12009-04-28 19:58:421117 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321118 request.method = "GET";
1119 request.url = GURL("http://www.google.com/");
1120 request.load_flags = 0;
1121
1122 MockWrite data_writes1[] = {
1123 MockWrite("GET / HTTP/1.1\r\n"
1124 "Host: www.google.com\r\n"
1125 "Connection: keep-alive\r\n\r\n"),
1126
1127 // After calling trans->RestartWithAuth(), this is the request we should
1128 // be issuing -- the final header line contains the credentials.
1129 MockWrite("GET / HTTP/1.1\r\n"
1130 "Host: www.google.com\r\n"
1131 "Connection: keep-alive\r\n"
1132 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1133 };
1134
[email protected]2d2697f92009-02-18 21:00:321135 MockRead data_reads1[] = {
1136 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1137 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311138 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321139
1140 // Lastly, the server responds with the actual content.
1141 MockRead("HTTP/1.1 200 OK\r\n"),
1142 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1143 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421144 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321145 };
1146
[email protected]31a2bfe2010-02-09 08:03:391147 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1148 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591149 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321150
1151 TestCompletionCallback callback1;
1152
[email protected]5a1d7ca2010-04-28 20:12:271153 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421154 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321155
1156 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421157 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321158
[email protected]1c773ea12009-04-28 19:58:421159 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321160 EXPECT_FALSE(response == NULL);
1161
1162 // The password prompt info should have been set in response->auth_challenge.
1163 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1164
[email protected]71e4573a2009-05-21 22:03:001165 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321166 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1167 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1168
1169 TestCompletionCallback callback2;
1170
[email protected]13c8a092010-07-29 06:15:441171 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421172 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321173
1174 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421175 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321176
1177 response = trans->GetResponseInfo();
1178 EXPECT_FALSE(response == NULL);
1179 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1180 EXPECT_EQ(100, response->headers->GetContentLength());
1181}
1182
1183// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1184// connection and with a large response body to drain.
1185TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591186 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401187 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431188 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321189
[email protected]1c773ea12009-04-28 19:58:421190 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321191 request.method = "GET";
1192 request.url = GURL("http://www.google.com/");
1193 request.load_flags = 0;
1194
1195 MockWrite data_writes1[] = {
1196 MockWrite("GET / HTTP/1.1\r\n"
1197 "Host: www.google.com\r\n"
1198 "Connection: keep-alive\r\n\r\n"),
1199
1200 // After calling trans->RestartWithAuth(), this is the request we should
1201 // be issuing -- the final header line contains the credentials.
1202 MockWrite("GET / HTTP/1.1\r\n"
1203 "Host: www.google.com\r\n"
1204 "Connection: keep-alive\r\n"
1205 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1206 };
1207
1208 // Respond with 5 kb of response body.
1209 std::string large_body_string("Unauthorized");
1210 large_body_string.append(5 * 1024, ' ');
1211 large_body_string.append("\r\n");
1212
1213 MockRead data_reads1[] = {
1214 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1215 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1217 // 5134 = 12 + 5 * 1024 + 2
1218 MockRead("Content-Length: 5134\r\n\r\n"),
1219 MockRead(true, large_body_string.data(), large_body_string.size()),
1220
1221 // Lastly, the server responds with the actual content.
1222 MockRead("HTTP/1.1 200 OK\r\n"),
1223 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1224 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421225 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321226 };
1227
[email protected]31a2bfe2010-02-09 08:03:391228 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1229 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591230 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321231
1232 TestCompletionCallback callback1;
1233
[email protected]5a1d7ca2010-04-28 20:12:271234 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421235 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321236
1237 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421238 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321239
[email protected]1c773ea12009-04-28 19:58:421240 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321241 EXPECT_FALSE(response == NULL);
1242
1243 // The password prompt info should have been set in response->auth_challenge.
1244 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1245
[email protected]71e4573a2009-05-21 22:03:001246 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321247 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1248 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1249
1250 TestCompletionCallback callback2;
1251
[email protected]13c8a092010-07-29 06:15:441252 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421253 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321254
1255 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421256 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321257
1258 response = trans->GetResponseInfo();
1259 EXPECT_FALSE(response == NULL);
1260 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1261 EXPECT_EQ(100, response->headers->GetContentLength());
1262}
1263
1264// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311265// connection, but the server gets impatient and closes the connection.
1266TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1267 SessionDependencies session_deps;
1268 scoped_ptr<HttpTransaction> trans(
1269 new HttpNetworkTransaction(CreateSession(&session_deps)));
1270
1271 HttpRequestInfo request;
1272 request.method = "GET";
1273 request.url = GURL("http://www.google.com/");
1274 request.load_flags = 0;
1275
1276 MockWrite data_writes1[] = {
1277 MockWrite("GET / HTTP/1.1\r\n"
1278 "Host: www.google.com\r\n"
1279 "Connection: keep-alive\r\n\r\n"),
1280 // This simulates the seemingly successful write to a closed connection
1281 // if the bug is not fixed.
1282 MockWrite("GET / HTTP/1.1\r\n"
1283 "Host: www.google.com\r\n"
1284 "Connection: keep-alive\r\n"
1285 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1286 };
1287
1288 MockRead data_reads1[] = {
1289 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1290 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1291 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1292 MockRead("Content-Length: 14\r\n\r\n"),
1293 // Tell MockTCPClientSocket to simulate the server closing the connection.
1294 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1295 MockRead("Unauthorized\r\n"),
1296 MockRead(false, OK), // The server closes the connection.
1297 };
1298
1299 // After calling trans->RestartWithAuth(), this is the request we should
1300 // be issuing -- the final header line contains the credentials.
1301 MockWrite data_writes2[] = {
1302 MockWrite("GET / HTTP/1.1\r\n"
1303 "Host: www.google.com\r\n"
1304 "Connection: keep-alive\r\n"
1305 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1306 };
1307
1308 // Lastly, the server responds with the actual content.
1309 MockRead data_reads2[] = {
1310 MockRead("HTTP/1.1 200 OK\r\n"),
1311 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1312 MockRead("Content-Length: 100\r\n\r\n"),
1313 MockRead(false, OK),
1314 };
1315
[email protected]31a2bfe2010-02-09 08:03:391316 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1317 data_writes1, arraysize(data_writes1));
1318 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1319 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311320 session_deps.socket_factory.AddSocketDataProvider(&data1);
1321 session_deps.socket_factory.AddSocketDataProvider(&data2);
1322
1323 TestCompletionCallback callback1;
1324
[email protected]5a1d7ca2010-04-28 20:12:271325 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311326 EXPECT_EQ(ERR_IO_PENDING, rv);
1327
1328 rv = callback1.WaitForResult();
1329 EXPECT_EQ(OK, rv);
1330
1331 const HttpResponseInfo* response = trans->GetResponseInfo();
1332 EXPECT_FALSE(response == NULL);
1333
1334 // The password prompt info should have been set in response->auth_challenge.
1335 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1336
1337 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1338 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1339 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1340
1341 TestCompletionCallback callback2;
1342
[email protected]13c8a092010-07-29 06:15:441343 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311344 EXPECT_EQ(ERR_IO_PENDING, rv);
1345
1346 rv = callback2.WaitForResult();
1347 EXPECT_EQ(OK, rv);
1348
1349 response = trans->GetResponseInfo();
1350 ASSERT_FALSE(response == NULL);
1351 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1352 EXPECT_EQ(100, response->headers->GetContentLength());
1353}
1354
[email protected]394816e92010-08-03 07:38:591355// Test the request-challenge-retry sequence for basic auth, over a connection
1356// that requires a restart when setting up an SSL tunnel.
1357TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1358 // Configure against proxy server "myproxy:70".
1359 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1360 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1361 session_deps.net_log = log.bound().net_log();
1362 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1363
1364 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1365
1366 HttpRequestInfo request;
1367 request.method = "GET";
1368 request.url = GURL("https://www.google.com/");
1369 // when the no authentication data flag is set.
1370 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1371
1372 // Since we have proxy, should try to establish tunnel.
1373 MockWrite data_writes1[] = {
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\r\n"),
1377
1378 // After calling trans->RestartWithAuth(), this is the request we should
1379 // be issuing -- the final header line contains the credentials.
1380 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1381 "Host: www.google.com\r\n"
1382 "Proxy-Connection: keep-alive\r\n"
1383 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1384
1385 MockWrite("GET / HTTP/1.1\r\n"
1386 "Host: www.google.com\r\n"
1387 "Connection: keep-alive\r\n\r\n"),
1388 };
1389
1390 // The proxy responds to the connect with a 407, using a persistent
1391 // connection.
1392 MockRead data_reads1[] = {
1393 // No credentials.
1394 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1395 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1396 MockRead("Proxy-Connection: close\r\n\r\n"),
1397
1398 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1399
1400 MockRead("HTTP/1.1 200 OK\r\n"),
1401 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1402 MockRead("Content-Length: 100\r\n\r\n"),
1403 MockRead(false, OK),
1404 };
1405
1406 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1407 data_writes1, arraysize(data_writes1));
1408 session_deps.socket_factory.AddSocketDataProvider(&data1);
1409 SSLSocketDataProvider ssl(true, OK);
1410 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1411
1412 TestCompletionCallback callback1;
1413
1414 int rv = trans->Start(&request, &callback1, log.bound());
1415 EXPECT_EQ(ERR_IO_PENDING, rv);
1416
1417 rv = callback1.WaitForResult();
1418 EXPECT_EQ(OK, rv);
1419 size_t pos = ExpectLogContainsSomewhere(
1420 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1421 NetLog::PHASE_NONE);
1422 ExpectLogContainsSomewhere(
1423 log.entries(), pos,
1424 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1425 NetLog::PHASE_NONE);
1426
1427 const HttpResponseInfo* response = trans->GetResponseInfo();
1428 ASSERT_FALSE(response == NULL);
1429
1430 EXPECT_EQ(407, response->headers->response_code());
1431 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1432
1433 // The password prompt info should have been set in response->auth_challenge.
1434 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1435
1436 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1437 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1438 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1439
1440 TestCompletionCallback callback2;
1441
1442 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1443 EXPECT_EQ(ERR_IO_PENDING, rv);
1444
1445 rv = callback2.WaitForResult();
1446 EXPECT_EQ(OK, rv);
1447
1448 response = trans->GetResponseInfo();
1449 ASSERT_FALSE(response == NULL);
1450
1451 EXPECT_TRUE(response->headers->IsKeepAlive());
1452 EXPECT_EQ(200, response->headers->response_code());
1453 EXPECT_EQ(100, response->headers->GetContentLength());
1454 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1455
1456 // The password prompt info should not be set.
1457 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1458}
1459
[email protected]11203f012009-11-12 23:02:311460// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321461// proxy connection, when setting up an SSL tunnel.
1462TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1463 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591464 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541465 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1466 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591467 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321468
[email protected]5695b8c2009-09-30 21:36:431469 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321470
[email protected]1c773ea12009-04-28 19:58:421471 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321472 request.method = "GET";
1473 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461474 // Ensure that proxy authentication is attempted even
1475 // when the no authentication data flag is set.
1476 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321477
1478 // Since we have proxy, should try to establish tunnel.
1479 MockWrite data_writes1[] = {
1480 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451481 "Host: www.google.com\r\n"
1482 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321483
1484 // After calling trans->RestartWithAuth(), this is the request we should
1485 // be issuing -- the final header line contains the credentials.
1486 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1487 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451488 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321489 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1490 };
1491
1492 // The proxy responds to the connect with a 407, using a persistent
1493 // connection.
1494 MockRead data_reads1[] = {
1495 // No credentials.
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 MockRead("0123456789"),
1500
1501 // Wrong credentials (wrong password).
1502 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1503 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1504 MockRead("Content-Length: 10\r\n\r\n"),
1505 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421506 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321507 };
1508
[email protected]31a2bfe2010-02-09 08:03:391509 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1510 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591511 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321512
1513 TestCompletionCallback callback1;
1514
[email protected]dbb83db2010-05-11 18:13:391515 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421516 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321517
1518 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421519 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391520 size_t pos = ExpectLogContainsSomewhere(
1521 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1522 NetLog::PHASE_NONE);
1523 ExpectLogContainsSomewhere(
1524 log.entries(), pos,
1525 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1526 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321527
[email protected]1c773ea12009-04-28 19:58:421528 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321529 EXPECT_FALSE(response == NULL);
1530
1531 EXPECT_TRUE(response->headers->IsKeepAlive());
1532 EXPECT_EQ(407, response->headers->response_code());
1533 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421534 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321535
1536 // The password prompt info should have been set in response->auth_challenge.
1537 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1538
[email protected]71e4573a2009-05-21 22:03:001539 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321540 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1541 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1542
1543 TestCompletionCallback callback2;
1544
1545 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441546 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421547 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321548
1549 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421550 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321551
1552 response = trans->GetResponseInfo();
1553 EXPECT_FALSE(response == NULL);
1554
1555 EXPECT_TRUE(response->headers->IsKeepAlive());
1556 EXPECT_EQ(407, response->headers->response_code());
1557 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421558 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321559
1560 // The password prompt info should have been set in response->auth_challenge.
1561 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1562
[email protected]71e4573a2009-05-21 22:03:001563 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321564 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1565 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131566
[email protected]e60e47a2010-07-14 03:37:181567 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1568 // out of scope.
1569 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321570}
1571
[email protected]a8e9b162009-03-12 00:06:441572// Test that we don't read the response body when we fail to establish a tunnel,
1573// even if the user cancels the proxy's auth attempt.
1574TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1575 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591576 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441577
[email protected]e44de5d2009-06-05 20:12:451578 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441579
[email protected]5695b8c2009-09-30 21:36:431580 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441581
[email protected]1c773ea12009-04-28 19:58:421582 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441583 request.method = "GET";
1584 request.url = GURL("https://www.google.com/");
1585 request.load_flags = 0;
1586
1587 // Since we have proxy, should try to establish tunnel.
1588 MockWrite data_writes[] = {
1589 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451590 "Host: www.google.com\r\n"
1591 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441592 };
1593
1594 // The proxy responds to the connect with a 407.
1595 MockRead data_reads[] = {
1596 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1597 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1598 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421599 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441600 };
1601
[email protected]31a2bfe2010-02-09 08:03:391602 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1603 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591604 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441605
1606 TestCompletionCallback callback;
1607
[email protected]5a1d7ca2010-04-28 20:12:271608 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421609 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441610
1611 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421612 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441613
[email protected]1c773ea12009-04-28 19:58:421614 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441615 EXPECT_FALSE(response == NULL);
1616
1617 EXPECT_TRUE(response->headers->IsKeepAlive());
1618 EXPECT_EQ(407, response->headers->response_code());
1619 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421620 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441621
1622 std::string response_data;
1623 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421624 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181625
1626 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1627 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441628}
1629
[email protected]8fdbcd22010-05-05 02:54:521630// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1631// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1632TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1633 // We are using a DIRECT connection (i.e. no proxy) for this session.
1634 SessionDependencies session_deps;
1635 scoped_ptr<HttpTransaction> trans(
1636 new HttpNetworkTransaction(CreateSession(&session_deps)));
1637
1638 HttpRequestInfo request;
1639 request.method = "GET";
1640 request.url = GURL("http://www.google.com/");
1641 request.load_flags = 0;
1642
1643 MockWrite data_writes1[] = {
1644 MockWrite("GET / HTTP/1.1\r\n"
1645 "Host: www.google.com\r\n"
1646 "Connection: keep-alive\r\n\r\n"),
1647 };
1648
1649 MockRead data_reads1[] = {
1650 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1651 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1652 // Large content-length -- won't matter, as connection will be reset.
1653 MockRead("Content-Length: 10000\r\n\r\n"),
1654 MockRead(false, ERR_FAILED),
1655 };
1656
1657 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1658 data_writes1, arraysize(data_writes1));
1659 session_deps.socket_factory.AddSocketDataProvider(&data1);
1660
1661 TestCompletionCallback callback;
1662
1663 int rv = trans->Start(&request, &callback, BoundNetLog());
1664 EXPECT_EQ(ERR_IO_PENDING, rv);
1665
1666 rv = callback.WaitForResult();
1667 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1668}
1669
[email protected]2df19bb2010-08-25 20:13:461670
1671// Test a simple get through an HTTPS Proxy.
1672TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1673 // Configure against https proxy server "proxy:70".
1674 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1675 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1676 session_deps.net_log = log.bound().net_log();
1677 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1678
1679 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1680
1681 HttpRequestInfo request;
1682 request.method = "GET";
1683 request.url = GURL("http://www.google.com/");
1684
1685 // Since we have proxy, should use full url
1686 MockWrite data_writes1[] = {
1687 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1688 "Host: www.google.com\r\n"
1689 "Proxy-Connection: keep-alive\r\n\r\n"),
1690 };
1691
1692 MockRead data_reads1[] = {
1693 MockRead("HTTP/1.1 200 OK\r\n"),
1694 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1695 MockRead("Content-Length: 100\r\n\r\n"),
1696 MockRead(false, OK),
1697 };
1698
1699 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1700 data_writes1, arraysize(data_writes1));
1701 session_deps.socket_factory.AddSocketDataProvider(&data1);
1702 SSLSocketDataProvider ssl(true, OK);
1703 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1704
1705 TestCompletionCallback callback1;
1706
1707 int rv = trans->Start(&request, &callback1, log.bound());
1708 EXPECT_EQ(ERR_IO_PENDING, rv);
1709
1710 rv = callback1.WaitForResult();
1711 EXPECT_EQ(OK, rv);
1712
1713 const HttpResponseInfo* response = trans->GetResponseInfo();
1714 ASSERT_FALSE(response == NULL);
1715
1716 EXPECT_TRUE(response->headers->IsKeepAlive());
1717 EXPECT_EQ(200, response->headers->response_code());
1718 EXPECT_EQ(100, response->headers->GetContentLength());
1719 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1720
1721 // The password prompt info should not be set.
1722 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1723}
1724
1725// Test the challenge-response-retry sequence through an HTTPS Proxy
1726TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
1727 // Configure against https proxy server "proxy:70".
1728 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1729 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1730 session_deps.net_log = log.bound().net_log();
1731 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1732
1733 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1734
1735 HttpRequestInfo request;
1736 request.method = "GET";
1737 request.url = GURL("http://www.google.com/");
1738 // when the no authentication data flag is set.
1739 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1740
1741 // Since we have proxy, should use full url
1742 MockWrite data_writes1[] = {
1743 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1744 "Host: www.google.com\r\n"
1745 "Proxy-Connection: keep-alive\r\n\r\n"),
1746
1747 // After calling trans->RestartWithAuth(), this is the request we should
1748 // be issuing -- the final header line contains the credentials.
1749 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1750 "Host: www.google.com\r\n"
1751 "Proxy-Connection: keep-alive\r\n"
1752 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1753 };
1754
1755 // The proxy responds to the GET with a 407, using a persistent
1756 // connection.
1757 MockRead data_reads1[] = {
1758 // No credentials.
1759 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1760 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1761 MockRead("Proxy-Connection: keep-alive\r\n"),
1762 MockRead("Content-Length: 0\r\n\r\n"),
1763
1764 MockRead("HTTP/1.1 200 OK\r\n"),
1765 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1766 MockRead("Content-Length: 100\r\n\r\n"),
1767 MockRead(false, OK),
1768 };
1769
1770 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1771 data_writes1, arraysize(data_writes1));
1772 session_deps.socket_factory.AddSocketDataProvider(&data1);
1773 SSLSocketDataProvider ssl(true, OK);
1774 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1775
1776 TestCompletionCallback callback1;
1777
1778 int rv = trans->Start(&request, &callback1, log.bound());
1779 EXPECT_EQ(ERR_IO_PENDING, rv);
1780
1781 rv = callback1.WaitForResult();
1782 EXPECT_EQ(OK, rv);
1783
1784 const HttpResponseInfo* response = trans->GetResponseInfo();
1785 ASSERT_FALSE(response == NULL);
1786
1787 EXPECT_EQ(407, response->headers->response_code());
1788 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1789
1790 // The password prompt info should have been set in response->auth_challenge.
1791 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1792
1793 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
1794 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1795 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1796
1797 TestCompletionCallback callback2;
1798
1799 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1800 EXPECT_EQ(ERR_IO_PENDING, rv);
1801
1802 rv = callback2.WaitForResult();
1803 EXPECT_EQ(OK, rv);
1804
1805 response = trans->GetResponseInfo();
1806 ASSERT_FALSE(response == NULL);
1807
1808 EXPECT_TRUE(response->headers->IsKeepAlive());
1809 EXPECT_EQ(200, response->headers->response_code());
1810 EXPECT_EQ(100, response->headers->GetContentLength());
1811 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1812
1813 // The password prompt info should not be set.
1814 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1815}
1816
[email protected]ff007e162009-05-23 09:13:151817void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081818 const MockRead& status, int expected_status) {
1819 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591820 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081821
[email protected]228ff742009-06-05 01:19:591822 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081823
[email protected]5695b8c2009-09-30 21:36:431824 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081825
[email protected]1c773ea12009-04-28 19:58:421826 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081827 request.method = "GET";
1828 request.url = GURL("https://www.google.com/");
1829 request.load_flags = 0;
1830
1831 // Since we have proxy, should try to establish tunnel.
1832 MockWrite data_writes[] = {
1833 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451834 "Host: www.google.com\r\n"
1835 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081836 };
1837
1838 MockRead data_reads[] = {
1839 status,
1840 MockRead("Content-Length: 10\r\n\r\n"),
1841 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421842 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081843 };
1844
[email protected]31a2bfe2010-02-09 08:03:391845 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1846 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591847 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081848
1849 TestCompletionCallback callback;
1850
[email protected]5a1d7ca2010-04-28 20:12:271851 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421852 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081853
1854 rv = callback.WaitForResult();
1855 EXPECT_EQ(expected_status, rv);
1856}
1857
[email protected]ff007e162009-05-23 09:13:151858void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081859 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421860 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081861}
1862
1863TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1864 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1865}
1866
1867TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1868 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1869}
1870
1871TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1872 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1873}
1874
1875TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1876 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1877}
1878
1879TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1880 ConnectStatusHelper(
1881 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1882}
1883
1884TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1885 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1886}
1887
1888TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1889 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1890}
1891
1892TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1893 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1894}
1895
1896TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1897 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1898}
1899
1900TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1901 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1902}
1903
1904TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1905 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1906}
1907
1908TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1909 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1910}
1911
1912TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1913 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1914}
1915
1916TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1917 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1918}
1919
1920TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1921 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1922}
1923
1924TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1925 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1926}
1927
1928TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1929 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1930}
1931
1932TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1933 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1934}
1935
1936TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1937 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1938}
1939
1940TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1941 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1942}
1943
1944TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1945 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1946}
1947
1948TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1949 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1950}
1951
1952TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1953 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1954}
1955
1956TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1957 ConnectStatusHelperWithExpectedStatus(
1958 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541959 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081960}
1961
1962TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1963 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1964}
1965
1966TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1967 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1968}
1969
1970TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1971 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1972}
1973
1974TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1975 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1976}
1977
1978TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1979 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1980}
1981
1982TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1983 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1984}
1985
1986TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1987 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1988}
1989
1990TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1991 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1992}
1993
1994TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1995 ConnectStatusHelper(
1996 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1997}
1998
1999TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2000 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2001}
2002
2003TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2004 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2005}
2006
2007TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2008 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2009}
2010
2011TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2012 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2013}
2014
2015TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2016 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2017}
2018
2019TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2020 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2021}
2022
2023TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2024 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2025}
2026
[email protected]038e9a32008-10-08 22:40:162027// Test the flow when both the proxy server AND origin server require
2028// authentication. Again, this uses basic auth for both since that is
2029// the simplest to mock.
2030TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:592031 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012032
[email protected]038e9a32008-10-08 22:40:162033 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422034 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432035 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162036
[email protected]1c773ea12009-04-28 19:58:422037 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162038 request.method = "GET";
2039 request.url = GURL("http://www.google.com/");
2040 request.load_flags = 0;
2041
[email protected]f9ee6b52008-11-08 06:46:232042 MockWrite data_writes1[] = {
2043 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2044 "Host: www.google.com\r\n"
2045 "Proxy-Connection: keep-alive\r\n\r\n"),
2046 };
2047
[email protected]038e9a32008-10-08 22:40:162048 MockRead data_reads1[] = {
2049 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2050 // Give a couple authenticate options (only the middle one is actually
2051 // supported).
[email protected]22927ad2009-09-21 19:56:192052 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162053 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2054 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2055 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2056 // Large content-length -- won't matter, as connection will be reset.
2057 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422058 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162059 };
2060
2061 // After calling trans->RestartWithAuth() the first time, this is the
2062 // request we should be issuing -- the final header line contains the
2063 // proxy's credentials.
2064 MockWrite data_writes2[] = {
2065 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2066 "Host: www.google.com\r\n"
2067 "Proxy-Connection: keep-alive\r\n"
2068 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2069 };
2070
2071 // Now the proxy server lets the request pass through to origin server.
2072 // The origin server responds with a 401.
2073 MockRead data_reads2[] = {
2074 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2075 // Note: We are using the same realm-name as the proxy server. This is
2076 // completely valid, as realms are unique across hosts.
2077 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2078 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2079 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422080 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162081 };
2082
2083 // After calling trans->RestartWithAuth() the second time, we should send
2084 // the credentials for both the proxy and origin server.
2085 MockWrite data_writes3[] = {
2086 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2087 "Host: www.google.com\r\n"
2088 "Proxy-Connection: keep-alive\r\n"
2089 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2090 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2091 };
2092
2093 // Lastly we get the desired content.
2094 MockRead data_reads3[] = {
2095 MockRead("HTTP/1.0 200 OK\r\n"),
2096 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2097 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422098 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162099 };
2100
[email protected]31a2bfe2010-02-09 08:03:392101 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2102 data_writes1, arraysize(data_writes1));
2103 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2104 data_writes2, arraysize(data_writes2));
2105 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2106 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592107 session_deps.socket_factory.AddSocketDataProvider(&data1);
2108 session_deps.socket_factory.AddSocketDataProvider(&data2);
2109 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162110
2111 TestCompletionCallback callback1;
2112
[email protected]5a1d7ca2010-04-28 20:12:272113 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422114 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162115
2116 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422117 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162118
[email protected]1c773ea12009-04-28 19:58:422119 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162120 EXPECT_FALSE(response == NULL);
2121
2122 // The password prompt info should have been set in response->auth_challenge.
2123 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2124
[email protected]71e4573a2009-05-21 22:03:002125 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162126 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2127 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2128
2129 TestCompletionCallback callback2;
2130
[email protected]13c8a092010-07-29 06:15:442131 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422132 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162133
2134 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422135 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162136
2137 response = trans->GetResponseInfo();
2138 EXPECT_FALSE(response == NULL);
2139 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2140
[email protected]71e4573a2009-05-21 22:03:002141 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162142 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2143 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2144
2145 TestCompletionCallback callback3;
2146
[email protected]13c8a092010-07-29 06:15:442147 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422148 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162149
2150 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422151 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162152
2153 response = trans->GetResponseInfo();
2154 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2155 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162156}
[email protected]4ddaf2502008-10-23 18:26:192157
[email protected]ea9dc9a2009-09-05 00:43:322158// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2159// can't hook into its internals to cause it to generate predictable NTLM
2160// authorization headers.
2161#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292162// The NTLM authentication unit tests were generated by capturing the HTTP
2163// requests and responses using Fiddler 2 and inspecting the generated random
2164// bytes in the debugger.
2165
2166// Enter the correct password and authenticate successfully.
2167TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422168 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112169 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592170 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402171 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432172 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:242173
[email protected]1c773ea12009-04-28 19:58:422174 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242175 request.method = "GET";
2176 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2177 request.load_flags = 0;
2178
2179 MockWrite data_writes1[] = {
2180 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2181 "Host: 172.22.68.17\r\n"
2182 "Connection: keep-alive\r\n\r\n"),
2183 };
2184
2185 MockRead data_reads1[] = {
2186 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042187 // Negotiate and NTLM are often requested together. However, we only want
2188 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2189 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242190 MockRead("WWW-Authenticate: NTLM\r\n"),
2191 MockRead("Connection: close\r\n"),
2192 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362193 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242194 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422195 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242196 };
2197
2198 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222199 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242200 // request we should be issuing -- the final header line contains a Type
2201 // 1 message.
2202 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2203 "Host: 172.22.68.17\r\n"
2204 "Connection: keep-alive\r\n"
2205 "Authorization: NTLM "
2206 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2207
2208 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2209 // (the credentials for the origin server). The second request continues
2210 // on the same connection.
2211 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2212 "Host: 172.22.68.17\r\n"
2213 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292214 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2215 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2216 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2217 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2218 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242219 };
2220
2221 MockRead data_reads2[] = {
2222 // The origin server responds with a Type 2 message.
2223 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2224 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292225 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242226 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2227 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2228 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2229 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2230 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2231 "BtAAAAAAA=\r\n"),
2232 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362233 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242234 MockRead("You are not authorized to view this page\r\n"),
2235
2236 // Lastly we get the desired content.
2237 MockRead("HTTP/1.1 200 OK\r\n"),
2238 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2239 MockRead("Content-Length: 13\r\n\r\n"),
2240 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422241 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242242 };
2243
[email protected]31a2bfe2010-02-09 08:03:392244 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2245 data_writes1, arraysize(data_writes1));
2246 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2247 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592248 session_deps.socket_factory.AddSocketDataProvider(&data1);
2249 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242250
2251 TestCompletionCallback callback1;
2252
[email protected]5a1d7ca2010-04-28 20:12:272253 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422254 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242255
2256 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422257 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242258
[email protected]0757e7702009-03-27 04:00:222259 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2260 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442261 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422262 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222263 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422264 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222265 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2266
[email protected]1c773ea12009-04-28 19:58:422267 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042268 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242269
[email protected]aef04272010-06-28 18:03:042270 // The password prompt info should have been set in
2271 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242272 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2273
[email protected]71e4573a2009-05-21 22:03:002274 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242275 EXPECT_EQ(L"", response->auth_challenge->realm);
2276 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2277
[email protected]0757e7702009-03-27 04:00:222278 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242279
[email protected]13c8a092010-07-29 06:15:442280 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422281 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242282
[email protected]0757e7702009-03-27 04:00:222283 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422284 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242285
2286 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042287 ASSERT_FALSE(response == NULL);
2288
[email protected]3f918782009-02-28 01:29:242289 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2290 EXPECT_EQ(13, response->headers->GetContentLength());
2291}
2292
[email protected]385a4672009-03-11 22:21:292293// Enter a wrong password, and then the correct one.
2294TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422295 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112296 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592297 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402298 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432299 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:292300
[email protected]1c773ea12009-04-28 19:58:422301 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292302 request.method = "GET";
2303 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2304 request.load_flags = 0;
2305
2306 MockWrite data_writes1[] = {
2307 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2308 "Host: 172.22.68.17\r\n"
2309 "Connection: keep-alive\r\n\r\n"),
2310 };
2311
2312 MockRead data_reads1[] = {
2313 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042314 // Negotiate and NTLM are often requested together. However, we only want
2315 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2316 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292317 MockRead("WWW-Authenticate: NTLM\r\n"),
2318 MockRead("Connection: close\r\n"),
2319 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362320 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292321 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422322 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292323 };
2324
2325 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222326 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292327 // request we should be issuing -- the final header line contains a Type
2328 // 1 message.
2329 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2330 "Host: 172.22.68.17\r\n"
2331 "Connection: keep-alive\r\n"
2332 "Authorization: NTLM "
2333 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2334
2335 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2336 // (the credentials for the origin server). The second request continues
2337 // on the same connection.
2338 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2339 "Host: 172.22.68.17\r\n"
2340 "Connection: keep-alive\r\n"
2341 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2342 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2343 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2344 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2345 "4Ww7b7E=\r\n\r\n"),
2346 };
2347
2348 MockRead data_reads2[] = {
2349 // The origin server responds with a Type 2 message.
2350 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2351 MockRead("WWW-Authenticate: NTLM "
2352 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2353 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2354 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2355 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2356 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2357 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2358 "BtAAAAAAA=\r\n"),
2359 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362360 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292361 MockRead("You are not authorized to view this page\r\n"),
2362
2363 // Wrong password.
2364 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292365 MockRead("WWW-Authenticate: NTLM\r\n"),
2366 MockRead("Connection: close\r\n"),
2367 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362368 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292369 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422370 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292371 };
2372
2373 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222374 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292375 // request we should be issuing -- the final header line contains a Type
2376 // 1 message.
2377 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2378 "Host: 172.22.68.17\r\n"
2379 "Connection: keep-alive\r\n"
2380 "Authorization: NTLM "
2381 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2382
2383 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2384 // (the credentials for the origin server). The second request continues
2385 // on the same connection.
2386 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2387 "Host: 172.22.68.17\r\n"
2388 "Connection: keep-alive\r\n"
2389 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2390 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2391 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2392 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2393 "+4MUm7c=\r\n\r\n"),
2394 };
2395
2396 MockRead data_reads3[] = {
2397 // The origin server responds with a Type 2 message.
2398 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2399 MockRead("WWW-Authenticate: NTLM "
2400 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2401 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2402 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2403 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2404 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2405 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2406 "BtAAAAAAA=\r\n"),
2407 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362408 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292409 MockRead("You are not authorized to view this page\r\n"),
2410
2411 // Lastly we get the desired content.
2412 MockRead("HTTP/1.1 200 OK\r\n"),
2413 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2414 MockRead("Content-Length: 13\r\n\r\n"),
2415 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422416 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292417 };
2418
[email protected]31a2bfe2010-02-09 08:03:392419 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2420 data_writes1, arraysize(data_writes1));
2421 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2422 data_writes2, arraysize(data_writes2));
2423 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2424 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592425 session_deps.socket_factory.AddSocketDataProvider(&data1);
2426 session_deps.socket_factory.AddSocketDataProvider(&data2);
2427 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292428
2429 TestCompletionCallback callback1;
2430
[email protected]5a1d7ca2010-04-28 20:12:272431 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422432 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292433
2434 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422435 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292436
[email protected]0757e7702009-03-27 04:00:222437 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292438 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442439 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422440 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292441 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422442 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222443 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292444
[email protected]1c773ea12009-04-28 19:58:422445 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292446 EXPECT_FALSE(response == NULL);
2447
2448 // The password prompt info should have been set in response->auth_challenge.
2449 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2450
[email protected]71e4573a2009-05-21 22:03:002451 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292452 EXPECT_EQ(L"", response->auth_challenge->realm);
2453 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2454
2455 TestCompletionCallback callback3;
2456
[email protected]0757e7702009-03-27 04:00:222457 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442458 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422459 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292460
2461 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422462 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292463
[email protected]0757e7702009-03-27 04:00:222464 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2465 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442466 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422467 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222468 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422469 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222470 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2471
2472 response = trans->GetResponseInfo();
2473 EXPECT_FALSE(response == NULL);
2474
2475 // The password prompt info should have been set in response->auth_challenge.
2476 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2477
[email protected]71e4573a2009-05-21 22:03:002478 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222479 EXPECT_EQ(L"", response->auth_challenge->realm);
2480 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2481
2482 TestCompletionCallback callback5;
2483
2484 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442485 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422486 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222487
2488 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422489 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222490
[email protected]385a4672009-03-11 22:21:292491 response = trans->GetResponseInfo();
2492 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2493 EXPECT_EQ(13, response->headers->GetContentLength());
2494}
[email protected]ea9dc9a2009-09-05 00:43:322495#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292496
[email protected]4ddaf2502008-10-23 18:26:192497// Test reading a server response which has only headers, and no body.
2498// After some maximum number of bytes is consumed, the transaction should
2499// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2500TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592501 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402502 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432503 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192504
[email protected]1c773ea12009-04-28 19:58:422505 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192506 request.method = "GET";
2507 request.url = GURL("http://www.google.com/");
2508 request.load_flags = 0;
2509
[email protected]b75b7b2f2009-10-06 00:54:532510 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432511 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532512 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192513
2514 MockRead data_reads[] = {
2515 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432516 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192517 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422518 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192519 };
[email protected]31a2bfe2010-02-09 08:03:392520 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592521 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192522
2523 TestCompletionCallback callback;
2524
[email protected]5a1d7ca2010-04-28 20:12:272525 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422526 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192527
2528 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422529 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192530
[email protected]1c773ea12009-04-28 19:58:422531 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192532 EXPECT_TRUE(response == NULL);
2533}
[email protected]f4e426b2008-11-05 00:24:492534
2535// Make sure that we don't try to reuse a TCPClientSocket when failing to
2536// establish tunnel.
2537// http://code.google.com/p/chromium/issues/detail?id=3772
2538TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2539 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592540 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012541
[email protected]228ff742009-06-05 01:19:592542 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492543
[email protected]5695b8c2009-09-30 21:36:432544 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492545
[email protected]1c773ea12009-04-28 19:58:422546 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492547 request.method = "GET";
2548 request.url = GURL("https://www.google.com/");
2549 request.load_flags = 0;
2550
2551 // Since we have proxy, should try to establish tunnel.
2552 MockWrite data_writes1[] = {
2553 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452554 "Host: www.google.com\r\n"
2555 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492556 };
2557
[email protected]77848d12008-11-14 00:00:222558 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492559 // connection. Usually a proxy would return 501 (not implemented),
2560 // or 200 (tunnel established).
2561 MockRead data_reads1[] = {
2562 MockRead("HTTP/1.1 404 Not Found\r\n"),
2563 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422564 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492565 };
2566
[email protected]31a2bfe2010-02-09 08:03:392567 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2568 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592569 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492570
2571 TestCompletionCallback callback1;
2572
[email protected]5a1d7ca2010-04-28 20:12:272573 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422574 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492575
2576 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422577 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492578
[email protected]1c773ea12009-04-28 19:58:422579 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082580 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492581
[email protected]b4404c02009-04-10 16:38:522582 // Empty the current queue. This is necessary because idle sockets are
2583 // added to the connection pool asynchronously with a PostTask.
2584 MessageLoop::current()->RunAllPending();
2585
[email protected]f4e426b2008-11-05 00:24:492586 // We now check to make sure the TCPClientSocket was not added back to
2587 // the pool.
[email protected]a937a06d2009-08-19 21:19:242588 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492589 trans.reset();
[email protected]b4404c02009-04-10 16:38:522590 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492591 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242592 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492593}
[email protected]372d34a2008-11-05 21:30:512594
[email protected]1b157c02009-04-21 01:55:402595// Make sure that we recycle a socket after reading all of the response body.
2596TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592597 SessionDependencies session_deps;
2598 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402599
[email protected]5695b8c2009-09-30 21:36:432600 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402601
[email protected]1c773ea12009-04-28 19:58:422602 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402603 request.method = "GET";
2604 request.url = GURL("http://www.google.com/");
2605 request.load_flags = 0;
2606
2607 MockRead data_reads[] = {
2608 // A part of the response body is received with the response headers.
2609 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2610 // The rest of the response body is received in two parts.
2611 MockRead("lo"),
2612 MockRead(" world"),
2613 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422614 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402615 };
2616
[email protected]31a2bfe2010-02-09 08:03:392617 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592618 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402619
2620 TestCompletionCallback callback;
2621
[email protected]5a1d7ca2010-04-28 20:12:272622 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422623 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402624
2625 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422626 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402627
[email protected]1c773ea12009-04-28 19:58:422628 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402629 EXPECT_TRUE(response != NULL);
2630
2631 EXPECT_TRUE(response->headers != NULL);
2632 std::string status_line = response->headers->GetStatusLine();
2633 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2634
[email protected]a937a06d2009-08-19 21:19:242635 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402636
2637 std::string response_data;
2638 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422639 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402640 EXPECT_EQ("hello world", response_data);
2641
2642 // Empty the current queue. This is necessary because idle sockets are
2643 // added to the connection pool asynchronously with a PostTask.
2644 MessageLoop::current()->RunAllPending();
2645
2646 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242647 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402648}
2649
[email protected]76a505b2010-08-25 06:23:002650// Make sure that we recycle a SSL socket after reading all of the response
2651// body.
2652TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
2653 SessionDependencies session_deps;
2654 HttpRequestInfo request;
2655 request.method = "GET";
2656 request.url = GURL("https://www.google.com/");
2657 request.load_flags = 0;
2658
2659 MockWrite data_writes[] = {
2660 MockWrite("GET / HTTP/1.1\r\n"
2661 "Host: www.google.com\r\n"
2662 "Connection: keep-alive\r\n\r\n"),
2663 };
2664
2665 MockRead data_reads[] = {
2666 MockRead("HTTP/1.1 200 OK\r\n"),
2667 MockRead("Content-Length: 11\r\n\r\n"),
2668 MockRead("hello world"),
2669 MockRead(false, OK),
2670 };
2671
2672 SSLSocketDataProvider ssl(true, OK);
2673 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2674
2675 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2676 data_writes, arraysize(data_writes));
2677 session_deps.socket_factory.AddSocketDataProvider(&data);
2678
2679 TestCompletionCallback callback;
2680
2681 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2682 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2683
2684 int rv = trans->Start(&request, &callback, BoundNetLog());
2685
2686 EXPECT_EQ(ERR_IO_PENDING, rv);
2687 EXPECT_EQ(OK, callback.WaitForResult());
2688
2689 const HttpResponseInfo* response = trans->GetResponseInfo();
2690 ASSERT_TRUE(response != NULL);
2691 ASSERT_TRUE(response->headers != NULL);
2692 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2693
2694 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2695
2696 std::string response_data;
2697 rv = ReadTransaction(trans.get(), &response_data);
2698 EXPECT_EQ(OK, rv);
2699 EXPECT_EQ("hello world", response_data);
2700
2701 // Empty the current queue. This is necessary because idle sockets are
2702 // added to the connection pool asynchronously with a PostTask.
2703 MessageLoop::current()->RunAllPending();
2704
2705 // We now check to make sure the socket was added back to the pool.
2706 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2707}
2708
2709// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
2710// from the pool and make sure that we recover okay.
2711TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
2712 SessionDependencies session_deps;
2713 HttpRequestInfo request;
2714 request.method = "GET";
2715 request.url = GURL("https://www.google.com/");
2716 request.load_flags = 0;
2717
2718 MockWrite data_writes[] = {
2719 MockWrite("GET / HTTP/1.1\r\n"
2720 "Host: www.google.com\r\n"
2721 "Connection: keep-alive\r\n\r\n"),
2722 MockWrite("GET / HTTP/1.1\r\n"
2723 "Host: www.google.com\r\n"
2724 "Connection: keep-alive\r\n\r\n"),
2725 };
2726
2727 MockRead data_reads[] = {
2728 MockRead("HTTP/1.1 200 OK\r\n"),
2729 MockRead("Content-Length: 11\r\n\r\n"),
2730 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2731 MockRead("hello world"),
2732 MockRead(true, 0, 0) // EOF
2733 };
2734
2735 SSLSocketDataProvider ssl(true, OK);
2736 SSLSocketDataProvider ssl2(true, OK);
2737 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2738 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2739
2740 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2741 data_writes, arraysize(data_writes));
2742 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
2743 data_writes, arraysize(data_writes));
2744 session_deps.socket_factory.AddSocketDataProvider(&data);
2745 session_deps.socket_factory.AddSocketDataProvider(&data2);
2746
2747 TestCompletionCallback callback;
2748
2749 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2750 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2751
2752 int rv = trans->Start(&request, &callback, BoundNetLog());
2753
2754 EXPECT_EQ(ERR_IO_PENDING, rv);
2755 EXPECT_EQ(OK, callback.WaitForResult());
2756
2757 const HttpResponseInfo* response = trans->GetResponseInfo();
2758 ASSERT_TRUE(response != NULL);
2759 ASSERT_TRUE(response->headers != NULL);
2760 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2761
2762 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2763
2764 std::string response_data;
2765 rv = ReadTransaction(trans.get(), &response_data);
2766 EXPECT_EQ(OK, rv);
2767 EXPECT_EQ("hello world", response_data);
2768
2769 // Empty the current queue. This is necessary because idle sockets are
2770 // added to the connection pool asynchronously with a PostTask.
2771 MessageLoop::current()->RunAllPending();
2772
2773 // We now check to make sure the socket was added back to the pool.
2774 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2775
2776 // Now start the second transaction, which should reuse the previous socket.
2777
2778 trans.reset(new HttpNetworkTransaction(session));
2779
2780 rv = trans->Start(&request, &callback, BoundNetLog());
2781
2782 EXPECT_EQ(ERR_IO_PENDING, rv);
2783 EXPECT_EQ(OK, callback.WaitForResult());
2784
2785 response = trans->GetResponseInfo();
2786 ASSERT_TRUE(response != NULL);
2787 ASSERT_TRUE(response->headers != NULL);
2788 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2789
2790 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2791
2792 rv = ReadTransaction(trans.get(), &response_data);
2793 EXPECT_EQ(OK, rv);
2794 EXPECT_EQ("hello world", response_data);
2795
2796 // Empty the current queue. This is necessary because idle sockets are
2797 // added to the connection pool asynchronously with a PostTask.
2798 MessageLoop::current()->RunAllPending();
2799
2800 // We now check to make sure the socket was added back to the pool.
2801 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2802}
2803
[email protected]b4404c02009-04-10 16:38:522804// Make sure that we recycle a socket after a zero-length response.
2805// http://crbug.com/9880
2806TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592807 SessionDependencies session_deps;
2808 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522809
[email protected]5695b8c2009-09-30 21:36:432810 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522811
[email protected]1c773ea12009-04-28 19:58:422812 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522813 request.method = "GET";
2814 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2815 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2816 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2817 "rt=prt.2642,ol.2649,xjs.2951");
2818 request.load_flags = 0;
2819
2820 MockRead data_reads[] = {
2821 MockRead("HTTP/1.1 204 No Content\r\n"
2822 "Content-Length: 0\r\n"
2823 "Content-Type: text/html\r\n\r\n"),
2824 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422825 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522826 };
2827
[email protected]31a2bfe2010-02-09 08:03:392828 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592829 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522830
2831 TestCompletionCallback callback;
2832
[email protected]5a1d7ca2010-04-28 20:12:272833 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422834 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522835
2836 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422837 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522838
[email protected]1c773ea12009-04-28 19:58:422839 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522840 EXPECT_TRUE(response != NULL);
2841
2842 EXPECT_TRUE(response->headers != NULL);
2843 std::string status_line = response->headers->GetStatusLine();
2844 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2845
[email protected]a937a06d2009-08-19 21:19:242846 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522847
2848 std::string response_data;
2849 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422850 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522851 EXPECT_EQ("", response_data);
2852
2853 // Empty the current queue. This is necessary because idle sockets are
2854 // added to the connection pool asynchronously with a PostTask.
2855 MessageLoop::current()->RunAllPending();
2856
2857 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242858 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522859}
2860
[email protected]372d34a2008-11-05 21:30:512861TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422862 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512863 // Transaction 1: a GET request that succeeds. The socket is recycled
2864 // after use.
2865 request[0].method = "GET";
2866 request[0].url = GURL("http://www.google.com/");
2867 request[0].load_flags = 0;
2868 // Transaction 2: a POST request. Reuses the socket kept alive from
2869 // transaction 1. The first attempts fails when writing the POST data.
2870 // This causes the transaction to retry with a new socket. The second
2871 // attempt succeeds.
2872 request[1].method = "POST";
2873 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422874 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512875 request[1].upload_data->AppendBytes("foo", 3);
2876 request[1].load_flags = 0;
2877
[email protected]228ff742009-06-05 01:19:592878 SessionDependencies session_deps;
2879 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512880
2881 // The first socket is used for transaction 1 and the first attempt of
2882 // transaction 2.
2883
2884 // The response of transaction 1.
2885 MockRead data_reads1[] = {
2886 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2887 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422888 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512889 };
2890 // The mock write results of transaction 1 and the first attempt of
2891 // transaction 2.
2892 MockWrite data_writes1[] = {
2893 MockWrite(false, 64), // GET
2894 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422895 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512896 };
[email protected]31a2bfe2010-02-09 08:03:392897 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2898 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512899
2900 // The second socket is used for the second attempt of transaction 2.
2901
2902 // The response of transaction 2.
2903 MockRead data_reads2[] = {
2904 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2905 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422906 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512907 };
2908 // The mock write results of the second attempt of transaction 2.
2909 MockWrite data_writes2[] = {
2910 MockWrite(false, 93), // POST
2911 MockWrite(false, 3), // POST data
2912 };
[email protected]31a2bfe2010-02-09 08:03:392913 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2914 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512915
[email protected]5ecc992a42009-11-11 01:41:592916 session_deps.socket_factory.AddSocketDataProvider(&data1);
2917 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512918
2919 const char* kExpectedResponseData[] = {
2920 "hello world", "welcome"
2921 };
2922
2923 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422924 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432925 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512926
2927 TestCompletionCallback callback;
2928
[email protected]5a1d7ca2010-04-28 20:12:272929 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422930 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512931
2932 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422933 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512934
[email protected]1c773ea12009-04-28 19:58:422935 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512936 EXPECT_TRUE(response != NULL);
2937
2938 EXPECT_TRUE(response->headers != NULL);
2939 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2940
2941 std::string response_data;
2942 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422943 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512944 EXPECT_EQ(kExpectedResponseData[i], response_data);
2945 }
2946}
[email protected]f9ee6b52008-11-08 06:46:232947
2948// Test the request-challenge-retry sequence for basic auth when there is
2949// an identity in the URL. The request should be sent as normal, but when
2950// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322951TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592952 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402953 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432954 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232955
[email protected]1c773ea12009-04-28 19:58:422956 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232957 request.method = "GET";
2958 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292959 request.url = GURL("http://foo:b@[email protected]/");
2960
2961 // The password contains an escaped character -- for this test to pass it
2962 // will need to be unescaped by HttpNetworkTransaction.
2963 EXPECT_EQ("b%40r", request.url.password());
2964
[email protected]ea9dc9a2009-09-05 00:43:322965 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232966
2967 MockWrite data_writes1[] = {
2968 MockWrite("GET / HTTP/1.1\r\n"
2969 "Host: www.google.com\r\n"
2970 "Connection: keep-alive\r\n\r\n"),
2971 };
2972
2973 MockRead data_reads1[] = {
2974 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2975 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2976 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422977 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232978 };
2979
2980 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322981 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232982 MockWrite data_writes2[] = {
2983 MockWrite("GET / HTTP/1.1\r\n"
2984 "Host: www.google.com\r\n"
2985 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292986 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232987 };
2988
2989 MockRead data_reads2[] = {
2990 MockRead("HTTP/1.0 200 OK\r\n"),
2991 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422992 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232993 };
2994
[email protected]31a2bfe2010-02-09 08:03:392995 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2996 data_writes1, arraysize(data_writes1));
2997 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2998 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592999 session_deps.socket_factory.AddSocketDataProvider(&data1);
3000 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233001
3002 TestCompletionCallback callback1;
3003
[email protected]5a1d7ca2010-04-28 20:12:273004 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423005 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233006
3007 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423008 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233009
[email protected]0757e7702009-03-27 04:00:223010 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3011 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443012 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423013 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223014 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423015 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223016 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3017
[email protected]1c773ea12009-04-28 19:58:423018 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233019 EXPECT_FALSE(response == NULL);
3020
3021 // There is no challenge info, since the identity in URL worked.
3022 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3023
3024 EXPECT_EQ(100, response->headers->GetContentLength());
3025
3026 // Empty the current queue.
3027 MessageLoop::current()->RunAllPending();
3028}
3029
[email protected]ea9dc9a2009-09-05 00:43:323030// Test the request-challenge-retry sequence for basic auth when there is
3031// an incorrect identity in the URL. The identity from the URL should be used
3032// only once.
3033TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3034 SessionDependencies session_deps;
3035 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433036 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323037
3038 HttpRequestInfo request;
3039 request.method = "GET";
3040 // Note: the URL has a username:password in it. The password "baz" is
3041 // wrong (should be "bar").
3042 request.url = GURL("http://foo:[email protected]/");
3043
3044 request.load_flags = LOAD_NORMAL;
3045
3046 MockWrite data_writes1[] = {
3047 MockWrite("GET / HTTP/1.1\r\n"
3048 "Host: www.google.com\r\n"
3049 "Connection: keep-alive\r\n\r\n"),
3050 };
3051
3052 MockRead data_reads1[] = {
3053 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3054 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3055 MockRead("Content-Length: 10\r\n\r\n"),
3056 MockRead(false, ERR_FAILED),
3057 };
3058
3059 // After the challenge above, the transaction will be restarted using the
3060 // identity from the url (foo, baz) to answer the challenge.
3061 MockWrite data_writes2[] = {
3062 MockWrite("GET / HTTP/1.1\r\n"
3063 "Host: www.google.com\r\n"
3064 "Connection: keep-alive\r\n"
3065 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3066 };
3067
3068 MockRead data_reads2[] = {
3069 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3070 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3071 MockRead("Content-Length: 10\r\n\r\n"),
3072 MockRead(false, ERR_FAILED),
3073 };
3074
3075 // After the challenge above, the transaction will be restarted using the
3076 // identity supplied by the user (foo, bar) to answer the challenge.
3077 MockWrite data_writes3[] = {
3078 MockWrite("GET / HTTP/1.1\r\n"
3079 "Host: www.google.com\r\n"
3080 "Connection: keep-alive\r\n"
3081 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3082 };
3083
3084 MockRead data_reads3[] = {
3085 MockRead("HTTP/1.0 200 OK\r\n"),
3086 MockRead("Content-Length: 100\r\n\r\n"),
3087 MockRead(false, OK),
3088 };
3089
[email protected]31a2bfe2010-02-09 08:03:393090 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3091 data_writes1, arraysize(data_writes1));
3092 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3093 data_writes2, arraysize(data_writes2));
3094 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3095 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593096 session_deps.socket_factory.AddSocketDataProvider(&data1);
3097 session_deps.socket_factory.AddSocketDataProvider(&data2);
3098 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323099
3100 TestCompletionCallback callback1;
3101
[email protected]5a1d7ca2010-04-28 20:12:273102 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323103 EXPECT_EQ(ERR_IO_PENDING, rv);
3104
3105 rv = callback1.WaitForResult();
3106 EXPECT_EQ(OK, rv);
3107
3108 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3109 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443110 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323111 EXPECT_EQ(ERR_IO_PENDING, rv);
3112 rv = callback2.WaitForResult();
3113 EXPECT_EQ(OK, rv);
3114 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3115
3116 const HttpResponseInfo* response = trans->GetResponseInfo();
3117 EXPECT_FALSE(response == NULL);
3118 // The password prompt info should have been set in response->auth_challenge.
3119 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3120
3121 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3122 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3123 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3124
3125 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443126 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323127 EXPECT_EQ(ERR_IO_PENDING, rv);
3128 rv = callback3.WaitForResult();
3129 EXPECT_EQ(OK, rv);
3130 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3131
3132 response = trans->GetResponseInfo();
3133 EXPECT_FALSE(response == NULL);
3134
3135 // There is no challenge info, since the identity worked.
3136 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3137
3138 EXPECT_EQ(100, response->headers->GetContentLength());
3139
3140 // Empty the current queue.
3141 MessageLoop::current()->RunAllPending();
3142}
3143
[email protected]f9ee6b52008-11-08 06:46:233144// Test that previously tried username/passwords for a realm get re-used.
3145TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593146 SessionDependencies session_deps;
3147 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:233148
3149 // Transaction 1: authenticate (foo, bar) on MyRealm1
3150 {
[email protected]5695b8c2009-09-30 21:36:433151 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233152
[email protected]1c773ea12009-04-28 19:58:423153 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233154 request.method = "GET";
3155 request.url = GURL("http://www.google.com/x/y/z");
3156 request.load_flags = 0;
3157
3158 MockWrite data_writes1[] = {
3159 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3160 "Host: www.google.com\r\n"
3161 "Connection: keep-alive\r\n\r\n"),
3162 };
3163
3164 MockRead data_reads1[] = {
3165 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3166 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3167 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423168 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233169 };
3170
3171 // Resend with authorization (username=foo, password=bar)
3172 MockWrite data_writes2[] = {
3173 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3174 "Host: www.google.com\r\n"
3175 "Connection: keep-alive\r\n"
3176 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3177 };
3178
3179 // Sever accepts the authorization.
3180 MockRead data_reads2[] = {
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));
3188 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3189 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593190 session_deps.socket_factory.AddSocketDataProvider(&data1);
3191 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233192
3193 TestCompletionCallback callback1;
3194
[email protected]5a1d7ca2010-04-28 20:12:273195 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423196 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233197
3198 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423199 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233200
[email protected]1c773ea12009-04-28 19:58:423201 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233202 EXPECT_FALSE(response == NULL);
3203
3204 // The password prompt info should have been set in
3205 // response->auth_challenge.
3206 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3207
[email protected]71e4573a2009-05-21 22:03:003208 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233209 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3210 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3211
3212 TestCompletionCallback callback2;
3213
[email protected]13c8a092010-07-29 06:15:443214 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423215 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233216
3217 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423218 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233219
3220 response = trans->GetResponseInfo();
3221 EXPECT_FALSE(response == NULL);
3222 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3223 EXPECT_EQ(100, response->headers->GetContentLength());
3224 }
3225
3226 // ------------------------------------------------------------------------
3227
3228 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3229 {
[email protected]5695b8c2009-09-30 21:36:433230 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233231
[email protected]1c773ea12009-04-28 19:58:423232 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233233 request.method = "GET";
3234 // Note that Transaction 1 was at /x/y/z, so this is in the same
3235 // protection space as MyRealm1.
3236 request.url = GURL("http://www.google.com/x/y/a/b");
3237 request.load_flags = 0;
3238
3239 MockWrite data_writes1[] = {
3240 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3241 "Host: www.google.com\r\n"
3242 "Connection: keep-alive\r\n"
3243 // Send preemptive authorization for MyRealm1
3244 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3245 };
3246
3247 // The server didn't like the preemptive authorization, and
3248 // challenges us for a different realm (MyRealm2).
3249 MockRead data_reads1[] = {
3250 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3251 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3252 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423253 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233254 };
3255
3256 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3257 MockWrite data_writes2[] = {
3258 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3259 "Host: www.google.com\r\n"
3260 "Connection: keep-alive\r\n"
3261 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3262 };
3263
3264 // Sever accepts the authorization.
3265 MockRead data_reads2[] = {
3266 MockRead("HTTP/1.0 200 OK\r\n"),
3267 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423268 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233269 };
3270
[email protected]31a2bfe2010-02-09 08:03:393271 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3272 data_writes1, arraysize(data_writes1));
3273 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3274 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593275 session_deps.socket_factory.AddSocketDataProvider(&data1);
3276 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233277
3278 TestCompletionCallback callback1;
3279
[email protected]5a1d7ca2010-04-28 20:12:273280 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423281 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233282
3283 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423284 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233285
[email protected]1c773ea12009-04-28 19:58:423286 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233287 EXPECT_FALSE(response == NULL);
3288
3289 // The password prompt info should have been set in
3290 // response->auth_challenge.
3291 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3292
[email protected]71e4573a2009-05-21 22:03:003293 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233294 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3295 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3296
3297 TestCompletionCallback callback2;
3298
[email protected]13c8a092010-07-29 06:15:443299 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423300 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233301
3302 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423303 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233304
3305 response = trans->GetResponseInfo();
3306 EXPECT_FALSE(response == NULL);
3307 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3308 EXPECT_EQ(100, response->headers->GetContentLength());
3309 }
3310
3311 // ------------------------------------------------------------------------
3312
3313 // Transaction 3: Resend a request in MyRealm's protection space --
3314 // succeed with preemptive authorization.
3315 {
[email protected]5695b8c2009-09-30 21:36:433316 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233317
[email protected]1c773ea12009-04-28 19:58:423318 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233319 request.method = "GET";
3320 request.url = GURL("http://www.google.com/x/y/z2");
3321 request.load_flags = 0;
3322
3323 MockWrite data_writes1[] = {
3324 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3325 "Host: www.google.com\r\n"
3326 "Connection: keep-alive\r\n"
3327 // The authorization for MyRealm1 gets sent preemptively
3328 // (since the url is in the same protection space)
3329 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3330 };
3331
3332 // Sever accepts the preemptive authorization
3333 MockRead data_reads1[] = {
3334 MockRead("HTTP/1.0 200 OK\r\n"),
3335 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423336 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233337 };
3338
[email protected]31a2bfe2010-02-09 08:03:393339 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3340 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593341 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233342
3343 TestCompletionCallback callback1;
3344
[email protected]5a1d7ca2010-04-28 20:12:273345 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423346 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233347
3348 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423349 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233350
[email protected]1c773ea12009-04-28 19:58:423351 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233352 EXPECT_FALSE(response == NULL);
3353
3354 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3355 EXPECT_EQ(100, response->headers->GetContentLength());
3356 }
3357
3358 // ------------------------------------------------------------------------
3359
3360 // Transaction 4: request another URL in MyRealm (however the
3361 // url is not known to belong to the protection space, so no pre-auth).
3362 {
[email protected]5695b8c2009-09-30 21:36:433363 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233364
[email protected]1c773ea12009-04-28 19:58:423365 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233366 request.method = "GET";
3367 request.url = GURL("http://www.google.com/x/1");
3368 request.load_flags = 0;
3369
3370 MockWrite data_writes1[] = {
3371 MockWrite("GET /x/1 HTTP/1.1\r\n"
3372 "Host: www.google.com\r\n"
3373 "Connection: keep-alive\r\n\r\n"),
3374 };
3375
3376 MockRead data_reads1[] = {
3377 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3378 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3379 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423380 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233381 };
3382
3383 // Resend with authorization from MyRealm's cache.
3384 MockWrite data_writes2[] = {
3385 MockWrite("GET /x/1 HTTP/1.1\r\n"
3386 "Host: www.google.com\r\n"
3387 "Connection: keep-alive\r\n"
3388 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3389 };
3390
3391 // Sever accepts the authorization.
3392 MockRead data_reads2[] = {
3393 MockRead("HTTP/1.0 200 OK\r\n"),
3394 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423395 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233396 };
3397
[email protected]31a2bfe2010-02-09 08:03:393398 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3399 data_writes1, arraysize(data_writes1));
3400 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3401 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593402 session_deps.socket_factory.AddSocketDataProvider(&data1);
3403 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233404
3405 TestCompletionCallback callback1;
3406
[email protected]5a1d7ca2010-04-28 20:12:273407 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423408 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233409
3410 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423411 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233412
[email protected]0757e7702009-03-27 04:00:223413 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3414 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443415 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423416 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223417 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423418 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223419 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3420
[email protected]1c773ea12009-04-28 19:58:423421 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233422 EXPECT_FALSE(response == NULL);
3423 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3424 EXPECT_EQ(100, response->headers->GetContentLength());
3425 }
3426
3427 // ------------------------------------------------------------------------
3428
3429 // Transaction 5: request a URL in MyRealm, but the server rejects the
3430 // cached identity. Should invalidate and re-prompt.
3431 {
[email protected]5695b8c2009-09-30 21:36:433432 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233433
[email protected]1c773ea12009-04-28 19:58:423434 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233435 request.method = "GET";
3436 request.url = GURL("http://www.google.com/p/q/t");
3437 request.load_flags = 0;
3438
3439 MockWrite data_writes1[] = {
3440 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3441 "Host: www.google.com\r\n"
3442 "Connection: keep-alive\r\n\r\n"),
3443 };
3444
3445 MockRead data_reads1[] = {
3446 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3447 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3448 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423449 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233450 };
3451
3452 // Resend with authorization from cache for MyRealm.
3453 MockWrite data_writes2[] = {
3454 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3455 "Host: www.google.com\r\n"
3456 "Connection: keep-alive\r\n"
3457 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3458 };
3459
3460 // Sever rejects the authorization.
3461 MockRead data_reads2[] = {
3462 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3463 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3464 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423465 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233466 };
3467
3468 // At this point we should prompt for new credentials for MyRealm.
3469 // Restart with username=foo3, password=foo4.
3470 MockWrite data_writes3[] = {
3471 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3472 "Host: www.google.com\r\n"
3473 "Connection: keep-alive\r\n"
3474 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3475 };
3476
3477 // Sever accepts the authorization.
3478 MockRead data_reads3[] = {
3479 MockRead("HTTP/1.0 200 OK\r\n"),
3480 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423481 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233482 };
3483
[email protected]31a2bfe2010-02-09 08:03:393484 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3485 data_writes1, arraysize(data_writes1));
3486 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3487 data_writes2, arraysize(data_writes2));
3488 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3489 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593490 session_deps.socket_factory.AddSocketDataProvider(&data1);
3491 session_deps.socket_factory.AddSocketDataProvider(&data2);
3492 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233493
3494 TestCompletionCallback callback1;
3495
[email protected]5a1d7ca2010-04-28 20:12:273496 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423497 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233498
3499 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423500 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233501
[email protected]0757e7702009-03-27 04:00:223502 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3503 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443504 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423505 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223506 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423507 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223508 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3509
[email protected]1c773ea12009-04-28 19:58:423510 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233511 EXPECT_FALSE(response == NULL);
3512
3513 // The password prompt info should have been set in
3514 // response->auth_challenge.
3515 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3516
[email protected]71e4573a2009-05-21 22:03:003517 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233518 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3519 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3520
[email protected]0757e7702009-03-27 04:00:223521 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233522
[email protected]13c8a092010-07-29 06:15:443523 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423524 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233525
[email protected]0757e7702009-03-27 04:00:223526 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423527 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233528
3529 response = trans->GetResponseInfo();
3530 EXPECT_FALSE(response == NULL);
3531 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3532 EXPECT_EQ(100, response->headers->GetContentLength());
3533 }
3534}
[email protected]89ceba9a2009-03-21 03:46:063535
[email protected]3c32c5f2010-05-18 15:18:123536// Tests that nonce count increments when multiple auth attempts
3537// are started with the same nonce.
3538TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3539 SessionDependencies session_deps;
3540 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3541 HttpAuthHandlerDigest::SetFixedCnonce(true);
3542
3543 // Transaction 1: authenticate (foo, bar) on MyRealm1
3544 {
3545 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3546
3547 HttpRequestInfo request;
3548 request.method = "GET";
3549 request.url = GURL("http://www.google.com/x/y/z");
3550 request.load_flags = 0;
3551
3552 MockWrite data_writes1[] = {
3553 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3554 "Host: www.google.com\r\n"
3555 "Connection: keep-alive\r\n\r\n"),
3556 };
3557
3558 MockRead data_reads1[] = {
3559 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3560 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3561 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3562 MockRead(false, OK),
3563 };
3564
3565 // Resend with authorization (username=foo, password=bar)
3566 MockWrite data_writes2[] = {
3567 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3568 "Host: www.google.com\r\n"
3569 "Connection: keep-alive\r\n"
3570 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3571 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3572 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3573 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3574 };
3575
3576 // Sever accepts the authorization.
3577 MockRead data_reads2[] = {
3578 MockRead("HTTP/1.0 200 OK\r\n"),
3579 MockRead(false, OK),
3580 };
3581
3582 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3583 data_writes1, arraysize(data_writes1));
3584 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3585 data_writes2, arraysize(data_writes2));
3586 session_deps.socket_factory.AddSocketDataProvider(&data1);
3587 session_deps.socket_factory.AddSocketDataProvider(&data2);
3588
3589 TestCompletionCallback callback1;
3590
3591 int rv = trans->Start(&request, &callback1, BoundNetLog());
3592 EXPECT_EQ(ERR_IO_PENDING, rv);
3593
3594 rv = callback1.WaitForResult();
3595 EXPECT_EQ(OK, rv);
3596
3597 const HttpResponseInfo* response = trans->GetResponseInfo();
3598 ASSERT_FALSE(response == NULL);
3599
3600 // The password prompt info should have been set in
3601 // response->auth_challenge.
3602 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3603
3604 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3605 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3606 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3607
3608 TestCompletionCallback callback2;
3609
[email protected]13c8a092010-07-29 06:15:443610 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123611 EXPECT_EQ(ERR_IO_PENDING, rv);
3612
3613 rv = callback2.WaitForResult();
3614 EXPECT_EQ(OK, rv);
3615
3616 response = trans->GetResponseInfo();
3617 ASSERT_FALSE(response == NULL);
3618 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3619 }
3620
3621 // ------------------------------------------------------------------------
3622
3623 // Transaction 2: Request another resource in digestive's protection space.
3624 // This will preemptively add an Authorization header which should have an
3625 // "nc" value of 2 (as compared to 1 in the first use.
3626 {
3627 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3628
3629 HttpRequestInfo request;
3630 request.method = "GET";
3631 // Note that Transaction 1 was at /x/y/z, so this is in the same
3632 // protection space as digest.
3633 request.url = GURL("http://www.google.com/x/y/a/b");
3634 request.load_flags = 0;
3635
3636 MockWrite data_writes1[] = {
3637 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3638 "Host: www.google.com\r\n"
3639 "Connection: keep-alive\r\n"
3640 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3641 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3642 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3643 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3644 };
3645
3646 // Sever accepts the authorization.
3647 MockRead data_reads1[] = {
3648 MockRead("HTTP/1.0 200 OK\r\n"),
3649 MockRead("Content-Length: 100\r\n\r\n"),
3650 MockRead(false, OK),
3651 };
3652
3653 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3654 data_writes1, arraysize(data_writes1));
3655 session_deps.socket_factory.AddSocketDataProvider(&data1);
3656
3657 TestCompletionCallback callback1;
3658
3659 int rv = trans->Start(&request, &callback1, BoundNetLog());
3660 EXPECT_EQ(ERR_IO_PENDING, rv);
3661
3662 rv = callback1.WaitForResult();
3663 EXPECT_EQ(OK, rv);
3664
3665 const HttpResponseInfo* response = trans->GetResponseInfo();
3666 ASSERT_FALSE(response == NULL);
3667 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3668 }
3669}
3670
[email protected]89ceba9a2009-03-21 03:46:063671// Test the ResetStateForRestart() private method.
3672TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3673 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593674 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403675 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433676 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063677
3678 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063679 trans->read_buf_ = new IOBuffer(15);
3680 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573681 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063682
3683 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143684 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573685 response->auth_challenge = new AuthChallengeInfo();
3686 response->ssl_info.cert_status = -15;
3687 response->response_time = base::Time::Now();
3688 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063689
3690 { // Setup state for response_.vary_data
3691 HttpRequestInfo request;
3692 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3693 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573694 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433695 request.extra_headers.SetHeader("Foo", "1");
3696 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573697 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063698 }
3699
3700 // Cause the above state to be reset.
3701 trans->ResetStateForRestart();
3702
3703 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073704 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063705 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573706 EXPECT_EQ(0U, trans->request_headers_.size());
3707 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3708 EXPECT_TRUE(response->headers.get() == NULL);
3709 EXPECT_EQ(false, response->was_cached);
3710 EXPECT_EQ(0, response->ssl_info.cert_status);
3711 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063712}
3713
[email protected]bacff652009-03-31 17:50:333714// Test HTTPS connections to a site with a bad certificate
3715TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593716 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403717 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433718 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333719
3720 HttpRequestInfo request;
3721 request.method = "GET";
3722 request.url = GURL("https://www.google.com/");
3723 request.load_flags = 0;
3724
3725 MockWrite data_writes[] = {
3726 MockWrite("GET / HTTP/1.1\r\n"
3727 "Host: www.google.com\r\n"
3728 "Connection: keep-alive\r\n\r\n"),
3729 };
3730
3731 MockRead data_reads[] = {
3732 MockRead("HTTP/1.0 200 OK\r\n"),
3733 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3734 MockRead("Content-Length: 100\r\n\r\n"),
3735 MockRead(false, OK),
3736 };
3737
[email protected]5ecc992a42009-11-11 01:41:593738 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393739 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3740 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593741 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3742 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333743
[email protected]5ecc992a42009-11-11 01:41:593744 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3745 session_deps.socket_factory.AddSocketDataProvider(&data);
3746 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3747 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333748
3749 TestCompletionCallback callback;
3750
[email protected]5a1d7ca2010-04-28 20:12:273751 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333752 EXPECT_EQ(ERR_IO_PENDING, rv);
3753
3754 rv = callback.WaitForResult();
3755 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3756
3757 rv = trans->RestartIgnoringLastError(&callback);
3758 EXPECT_EQ(ERR_IO_PENDING, rv);
3759
3760 rv = callback.WaitForResult();
3761 EXPECT_EQ(OK, rv);
3762
3763 const HttpResponseInfo* response = trans->GetResponseInfo();
3764
3765 EXPECT_FALSE(response == NULL);
3766 EXPECT_EQ(100, response->headers->GetContentLength());
3767}
3768
3769// Test HTTPS connections to a site with a bad certificate, going through a
3770// proxy
3771TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593772 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333773
3774 HttpRequestInfo request;
3775 request.method = "GET";
3776 request.url = GURL("https://www.google.com/");
3777 request.load_flags = 0;
3778
3779 MockWrite proxy_writes[] = {
3780 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453781 "Host: www.google.com\r\n"
3782 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333783 };
3784
3785 MockRead proxy_reads[] = {
3786 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423787 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333788 };
3789
3790 MockWrite data_writes[] = {
3791 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453792 "Host: www.google.com\r\n"
3793 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333794 MockWrite("GET / HTTP/1.1\r\n"
3795 "Host: www.google.com\r\n"
3796 "Connection: keep-alive\r\n\r\n"),
3797 };
3798
3799 MockRead data_reads[] = {
3800 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3801 MockRead("HTTP/1.0 200 OK\r\n"),
3802 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3803 MockRead("Content-Length: 100\r\n\r\n"),
3804 MockRead(false, OK),
3805 };
3806
[email protected]31a2bfe2010-02-09 08:03:393807 StaticSocketDataProvider ssl_bad_certificate(
3808 proxy_reads, arraysize(proxy_reads),
3809 proxy_writes, arraysize(proxy_writes));
3810 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3811 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593812 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3813 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333814
[email protected]5ecc992a42009-11-11 01:41:593815 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3816 session_deps.socket_factory.AddSocketDataProvider(&data);
3817 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3818 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333819
3820 TestCompletionCallback callback;
3821
3822 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593823 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333824
[email protected]d207a5f2009-06-04 05:28:403825 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433826 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333827
[email protected]5a1d7ca2010-04-28 20:12:273828 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333829 EXPECT_EQ(ERR_IO_PENDING, rv);
3830
3831 rv = callback.WaitForResult();
3832 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3833
3834 rv = trans->RestartIgnoringLastError(&callback);
3835 EXPECT_EQ(ERR_IO_PENDING, rv);
3836
3837 rv = callback.WaitForResult();
3838 EXPECT_EQ(OK, rv);
3839
3840 const HttpResponseInfo* response = trans->GetResponseInfo();
3841
3842 EXPECT_FALSE(response == NULL);
3843 EXPECT_EQ(100, response->headers->GetContentLength());
3844 }
3845}
3846
[email protected]2df19bb2010-08-25 20:13:463847
3848// Test HTTPS connections to a site, going through an HTTPS proxy
3849TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
3850 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
3851
3852 HttpRequestInfo request;
3853 request.method = "GET";
3854 request.url = GURL("https://www.google.com/");
3855 request.load_flags = 0;
3856
3857 MockWrite data_writes[] = {
3858 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3859 "Host: www.google.com\r\n"
3860 "Proxy-Connection: keep-alive\r\n\r\n"),
3861 MockWrite("GET / HTTP/1.1\r\n"
3862 "Host: www.google.com\r\n"
3863 "Connection: keep-alive\r\n\r\n"),
3864 };
3865
3866 MockRead data_reads[] = {
3867 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3868 MockRead("HTTP/1.1 200 OK\r\n"),
3869 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3870 MockRead("Content-Length: 100\r\n\r\n"),
3871 MockRead(false, OK),
3872 };
3873
3874 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3875 data_writes, arraysize(data_writes));
3876 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
3877 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
3878
3879 session_deps.socket_factory.AddSocketDataProvider(&data);
3880 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
3881 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
3882
3883 TestCompletionCallback callback;
3884
3885 scoped_ptr<HttpTransaction> trans(
3886 new HttpNetworkTransaction(CreateSession(&session_deps)));
3887
3888 int rv = trans->Start(&request, &callback, BoundNetLog());
3889 EXPECT_EQ(ERR_IO_PENDING, rv);
3890
3891 rv = callback.WaitForResult();
3892 EXPECT_EQ(OK, rv);
3893 const HttpResponseInfo* response = trans->GetResponseInfo();
3894
3895 ASSERT_FALSE(response == NULL);
3896
3897 EXPECT_TRUE(response->headers->IsKeepAlive());
3898 EXPECT_EQ(200, response->headers->response_code());
3899 EXPECT_EQ(100, response->headers->GetContentLength());
3900 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
3901}
3902
3903// Test HTTPS connections to a site with a bad certificate, going through an
3904// HTTPS proxy
3905TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
3906 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
3907
3908 HttpRequestInfo request;
3909 request.method = "GET";
3910 request.url = GURL("https://www.google.com/");
3911 request.load_flags = 0;
3912
3913 // Attempt to fetch the URL from a server with a bad cert
3914 MockWrite bad_cert_writes[] = {
3915 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3916 "Host: www.google.com\r\n"
3917 "Proxy-Connection: keep-alive\r\n\r\n"),
3918 };
3919
3920 MockRead bad_cert_reads[] = {
3921 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3922 MockRead(false, OK)
3923 };
3924
3925 // Attempt to fetch the URL with a good cert
3926 MockWrite good_data_writes[] = {
3927 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3928 "Host: www.google.com\r\n"
3929 "Proxy-Connection: keep-alive\r\n\r\n"),
3930 MockWrite("GET / HTTP/1.1\r\n"
3931 "Host: www.google.com\r\n"
3932 "Connection: keep-alive\r\n\r\n"),
3933 };
3934
3935 MockRead good_cert_reads[] = {
3936 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3937 MockRead("HTTP/1.0 200 OK\r\n"),
3938 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3939 MockRead("Content-Length: 100\r\n\r\n"),
3940 MockRead(false, OK),
3941 };
3942
3943 StaticSocketDataProvider ssl_bad_certificate(
3944 bad_cert_reads, arraysize(bad_cert_reads),
3945 bad_cert_writes, arraysize(bad_cert_writes));
3946 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
3947 good_data_writes, arraysize(good_data_writes));
3948 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3949 SSLSocketDataProvider ssl(true, OK);
3950
3951 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
3952 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3953 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3954 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3955
3956 // SSL to the proxy, then CONNECT request, then valid SSL certificate
3957 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3958 session_deps.socket_factory.AddSocketDataProvider(&data);
3959 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3960
3961 TestCompletionCallback callback;
3962
3963 scoped_ptr<HttpTransaction> trans(
3964 new HttpNetworkTransaction(CreateSession(&session_deps)));
3965
3966 int rv = trans->Start(&request, &callback, BoundNetLog());
3967 EXPECT_EQ(ERR_IO_PENDING, rv);
3968
3969 rv = callback.WaitForResult();
3970 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3971
3972 rv = trans->RestartIgnoringLastError(&callback);
3973 EXPECT_EQ(ERR_IO_PENDING, rv);
3974
3975 rv = callback.WaitForResult();
3976 EXPECT_EQ(OK, rv);
3977
3978 const HttpResponseInfo* response = trans->GetResponseInfo();
3979
3980 EXPECT_FALSE(response == NULL);
3981 EXPECT_EQ(100, response->headers->GetContentLength());
3982}
3983
[email protected]1c773ea12009-04-28 19:58:423984TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593985 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403986 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433987 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423988
3989 HttpRequestInfo request;
3990 request.method = "GET";
3991 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433992 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3993 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423994
3995 MockWrite data_writes[] = {
3996 MockWrite("GET / HTTP/1.1\r\n"
3997 "Host: www.google.com\r\n"
3998 "Connection: keep-alive\r\n"
3999 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4000 };
4001
4002 // Lastly, the server responds with the actual content.
4003 MockRead data_reads[] = {
4004 MockRead("HTTP/1.0 200 OK\r\n"),
4005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4006 MockRead("Content-Length: 100\r\n\r\n"),
4007 MockRead(false, OK),
4008 };
4009
[email protected]31a2bfe2010-02-09 08:03:394010 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4011 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594012 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424013
4014 TestCompletionCallback callback;
4015
[email protected]5a1d7ca2010-04-28 20:12:274016 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424017 EXPECT_EQ(ERR_IO_PENDING, rv);
4018
4019 rv = callback.WaitForResult();
4020 EXPECT_EQ(OK, rv);
4021}
4022
[email protected]da81f132010-08-18 23:39:294023TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
4024 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4025 scoped_ptr<HttpTransaction> trans(
4026 new HttpNetworkTransaction(CreateSession(&session_deps)));
4027
4028 HttpRequestInfo request;
4029 request.method = "GET";
4030 request.url = GURL("https://www.google.com/");
4031 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4032 "Chromium Ultra Awesome X Edition");
4033
4034 MockWrite data_writes[] = {
4035 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4036 "Host: www.google.com\r\n"
4037 "Proxy-Connection: keep-alive\r\n"
4038 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4039 };
4040 MockRead data_reads[] = {
4041 // Return an error, so the transaction stops here (this test isn't
4042 // interested in the rest).
4043 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4044 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4045 MockRead("Proxy-Connection: close\r\n\r\n"),
4046 };
4047
4048 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4049 data_writes, arraysize(data_writes));
4050 session_deps.socket_factory.AddSocketDataProvider(&data);
4051
4052 TestCompletionCallback callback;
4053
4054 int rv = trans->Start(&request, &callback, BoundNetLog());
4055 EXPECT_EQ(ERR_IO_PENDING, rv);
4056
4057 rv = callback.WaitForResult();
4058 EXPECT_EQ(OK, rv);
4059}
4060
[email protected]1c773ea12009-04-28 19:58:424061TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594062 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404063 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434064 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424065
4066 HttpRequestInfo request;
4067 request.method = "GET";
4068 request.url = GURL("http://www.google.com/");
4069 request.load_flags = 0;
4070 request.referrer = GURL("http://the.previous.site.com/");
4071
4072 MockWrite data_writes[] = {
4073 MockWrite("GET / HTTP/1.1\r\n"
4074 "Host: www.google.com\r\n"
4075 "Connection: keep-alive\r\n"
4076 "Referer: http://the.previous.site.com/\r\n\r\n"),
4077 };
4078
4079 // Lastly, the server responds with the actual content.
4080 MockRead data_reads[] = {
4081 MockRead("HTTP/1.0 200 OK\r\n"),
4082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4083 MockRead("Content-Length: 100\r\n\r\n"),
4084 MockRead(false, OK),
4085 };
4086
[email protected]31a2bfe2010-02-09 08:03:394087 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4088 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594089 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424090
4091 TestCompletionCallback callback;
4092
[email protected]5a1d7ca2010-04-28 20:12:274093 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424094 EXPECT_EQ(ERR_IO_PENDING, rv);
4095
4096 rv = callback.WaitForResult();
4097 EXPECT_EQ(OK, rv);
4098}
4099
4100TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594101 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404102 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434103 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424104
4105 HttpRequestInfo request;
4106 request.method = "POST";
4107 request.url = GURL("http://www.google.com/");
4108
4109 MockWrite data_writes[] = {
4110 MockWrite("POST / HTTP/1.1\r\n"
4111 "Host: www.google.com\r\n"
4112 "Connection: keep-alive\r\n"
4113 "Content-Length: 0\r\n\r\n"),
4114 };
4115
4116 // Lastly, the server responds with the actual content.
4117 MockRead data_reads[] = {
4118 MockRead("HTTP/1.0 200 OK\r\n"),
4119 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4120 MockRead("Content-Length: 100\r\n\r\n"),
4121 MockRead(false, OK),
4122 };
4123
[email protected]31a2bfe2010-02-09 08:03:394124 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4125 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594126 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424127
4128 TestCompletionCallback callback;
4129
[email protected]5a1d7ca2010-04-28 20:12:274130 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424131 EXPECT_EQ(ERR_IO_PENDING, rv);
4132
4133 rv = callback.WaitForResult();
4134 EXPECT_EQ(OK, rv);
4135}
4136
4137TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594138 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404139 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434140 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424141
4142 HttpRequestInfo request;
4143 request.method = "PUT";
4144 request.url = GURL("http://www.google.com/");
4145
4146 MockWrite data_writes[] = {
4147 MockWrite("PUT / HTTP/1.1\r\n"
4148 "Host: www.google.com\r\n"
4149 "Connection: keep-alive\r\n"
4150 "Content-Length: 0\r\n\r\n"),
4151 };
4152
4153 // Lastly, the server responds with the actual content.
4154 MockRead data_reads[] = {
4155 MockRead("HTTP/1.0 200 OK\r\n"),
4156 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4157 MockRead("Content-Length: 100\r\n\r\n"),
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]1c773ea12009-04-28 19:58:424164
4165 TestCompletionCallback callback;
4166
[email protected]5a1d7ca2010-04-28 20:12:274167 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424168 EXPECT_EQ(ERR_IO_PENDING, rv);
4169
4170 rv = callback.WaitForResult();
4171 EXPECT_EQ(OK, rv);
4172}
4173
4174TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594175 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404176 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434177 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424178
4179 HttpRequestInfo request;
4180 request.method = "HEAD";
4181 request.url = GURL("http://www.google.com/");
4182
4183 MockWrite data_writes[] = {
4184 MockWrite("HEAD / HTTP/1.1\r\n"
4185 "Host: www.google.com\r\n"
4186 "Connection: keep-alive\r\n"
4187 "Content-Length: 0\r\n\r\n"),
4188 };
4189
4190 // Lastly, the server responds with the actual content.
4191 MockRead data_reads[] = {
4192 MockRead("HTTP/1.0 200 OK\r\n"),
4193 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4194 MockRead("Content-Length: 100\r\n\r\n"),
4195 MockRead(false, OK),
4196 };
4197
[email protected]31a2bfe2010-02-09 08:03:394198 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4199 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594200 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424201
4202 TestCompletionCallback callback;
4203
[email protected]5a1d7ca2010-04-28 20:12:274204 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424205 EXPECT_EQ(ERR_IO_PENDING, rv);
4206
4207 rv = callback.WaitForResult();
4208 EXPECT_EQ(OK, rv);
4209}
4210
4211TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:594212 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404213 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434214 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424215
4216 HttpRequestInfo request;
4217 request.method = "GET";
4218 request.url = GURL("http://www.google.com/");
4219 request.load_flags = LOAD_BYPASS_CACHE;
4220
4221 MockWrite data_writes[] = {
4222 MockWrite("GET / HTTP/1.1\r\n"
4223 "Host: www.google.com\r\n"
4224 "Connection: keep-alive\r\n"
4225 "Pragma: no-cache\r\n"
4226 "Cache-Control: no-cache\r\n\r\n"),
4227 };
4228
4229 // Lastly, the server responds with the actual content.
4230 MockRead data_reads[] = {
4231 MockRead("HTTP/1.0 200 OK\r\n"),
4232 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4233 MockRead("Content-Length: 100\r\n\r\n"),
4234 MockRead(false, OK),
4235 };
4236
[email protected]31a2bfe2010-02-09 08:03:394237 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4238 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594239 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424240
4241 TestCompletionCallback callback;
4242
[email protected]5a1d7ca2010-04-28 20:12:274243 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424244 EXPECT_EQ(ERR_IO_PENDING, rv);
4245
4246 rv = callback.WaitForResult();
4247 EXPECT_EQ(OK, rv);
4248}
4249
4250TEST_F(HttpNetworkTransactionTest,
4251 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:594252 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404253 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434254 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424255
4256 HttpRequestInfo request;
4257 request.method = "GET";
4258 request.url = GURL("http://www.google.com/");
4259 request.load_flags = LOAD_VALIDATE_CACHE;
4260
4261 MockWrite data_writes[] = {
4262 MockWrite("GET / HTTP/1.1\r\n"
4263 "Host: www.google.com\r\n"
4264 "Connection: keep-alive\r\n"
4265 "Cache-Control: max-age=0\r\n\r\n"),
4266 };
4267
4268 // Lastly, the server responds with the actual content.
4269 MockRead data_reads[] = {
4270 MockRead("HTTP/1.0 200 OK\r\n"),
4271 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4272 MockRead("Content-Length: 100\r\n\r\n"),
4273 MockRead(false, OK),
4274 };
4275
[email protected]31a2bfe2010-02-09 08:03:394276 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4277 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594278 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424279
4280 TestCompletionCallback callback;
4281
[email protected]5a1d7ca2010-04-28 20:12:274282 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424283 EXPECT_EQ(ERR_IO_PENDING, rv);
4284
4285 rv = callback.WaitForResult();
4286 EXPECT_EQ(OK, rv);
4287}
4288
4289TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594290 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404291 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434292 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424293
4294 HttpRequestInfo request;
4295 request.method = "GET";
4296 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434297 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424298
4299 MockWrite data_writes[] = {
4300 MockWrite("GET / HTTP/1.1\r\n"
4301 "Host: www.google.com\r\n"
4302 "Connection: keep-alive\r\n"
4303 "FooHeader: Bar\r\n\r\n"),
4304 };
4305
4306 // Lastly, the server responds with the actual content.
4307 MockRead data_reads[] = {
4308 MockRead("HTTP/1.0 200 OK\r\n"),
4309 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4310 MockRead("Content-Length: 100\r\n\r\n"),
4311 MockRead(false, OK),
4312 };
4313
[email protected]31a2bfe2010-02-09 08:03:394314 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4315 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594316 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424317
4318 TestCompletionCallback callback;
4319
[email protected]5a1d7ca2010-04-28 20:12:274320 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424321 EXPECT_EQ(ERR_IO_PENDING, rv);
4322
4323 rv = callback.WaitForResult();
4324 EXPECT_EQ(OK, rv);
4325}
4326
[email protected]270c6412010-03-29 22:02:474327TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4328 SessionDependencies session_deps;
4329 scoped_ptr<HttpTransaction> trans(
4330 new HttpNetworkTransaction(CreateSession(&session_deps)));
4331
4332 HttpRequestInfo request;
4333 request.method = "GET";
4334 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434335 request.extra_headers.SetHeader("referer", "www.foo.com");
4336 request.extra_headers.SetHeader("hEllo", "Kitty");
4337 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474338
4339 MockWrite data_writes[] = {
4340 MockWrite("GET / HTTP/1.1\r\n"
4341 "Host: www.google.com\r\n"
4342 "Connection: keep-alive\r\n"
4343 "hEllo: Kitty\r\n"
4344 "FoO: bar\r\n\r\n"),
4345 };
4346
4347 // Lastly, the server responds with the actual content.
4348 MockRead data_reads[] = {
4349 MockRead("HTTP/1.0 200 OK\r\n"),
4350 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4351 MockRead("Content-Length: 100\r\n\r\n"),
4352 MockRead(false, OK),
4353 };
4354
4355 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4356 data_writes, arraysize(data_writes));
4357 session_deps.socket_factory.AddSocketDataProvider(&data);
4358
4359 TestCompletionCallback callback;
4360
[email protected]5a1d7ca2010-04-28 20:12:274361 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474362 EXPECT_EQ(ERR_IO_PENDING, rv);
4363
4364 rv = callback.WaitForResult();
4365 EXPECT_EQ(OK, rv);
4366}
4367
[email protected]3cd17242009-06-23 02:59:024368TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094369 SessionDependencies session_deps(
4370 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024371
4372 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434373 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024374
4375 HttpRequestInfo request;
4376 request.method = "GET";
4377 request.url = GURL("http://www.google.com/");
4378 request.load_flags = 0;
4379
4380 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4381 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4382
4383 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354384 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024385 MockWrite("GET / HTTP/1.1\r\n"
4386 "Host: www.google.com\r\n"
4387 "Connection: keep-alive\r\n\r\n")
4388 };
4389
4390 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594391 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024392 MockRead("HTTP/1.0 200 OK\r\n"),
4393 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4394 MockRead("Payload"),
4395 MockRead(false, OK)
4396 };
4397
[email protected]31a2bfe2010-02-09 08:03:394398 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4399 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594400 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024401
4402 TestCompletionCallback callback;
4403
[email protected]5a1d7ca2010-04-28 20:12:274404 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024405 EXPECT_EQ(ERR_IO_PENDING, rv);
4406
4407 rv = callback.WaitForResult();
4408 EXPECT_EQ(OK, rv);
4409
4410 const HttpResponseInfo* response = trans->GetResponseInfo();
4411 EXPECT_FALSE(response == NULL);
4412
4413 std::string response_text;
4414 rv = ReadTransaction(trans.get(), &response_text);
4415 EXPECT_EQ(OK, rv);
4416 EXPECT_EQ("Payload", response_text);
4417}
4418
4419TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094420 SessionDependencies session_deps(
4421 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024422
4423 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434424 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024425
4426 HttpRequestInfo request;
4427 request.method = "GET";
4428 request.url = GURL("https://www.google.com/");
4429 request.load_flags = 0;
4430
4431 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4432 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4433
4434 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354435 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4436 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024437 MockWrite("GET / HTTP/1.1\r\n"
4438 "Host: www.google.com\r\n"
4439 "Connection: keep-alive\r\n\r\n")
4440 };
4441
4442 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354443 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4444 arraysize(read_buffer)),
4445 MockRead("HTTP/1.0 200 OK\r\n"),
4446 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4447 MockRead("Payload"),
4448 MockRead(false, OK)
4449 };
4450
[email protected]31a2bfe2010-02-09 08:03:394451 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4452 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594453 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354454
[email protected]5ecc992a42009-11-11 01:41:594455 SSLSocketDataProvider ssl(true, OK);
4456 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354457
4458 TestCompletionCallback callback;
4459
[email protected]5a1d7ca2010-04-28 20:12:274460 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354461 EXPECT_EQ(ERR_IO_PENDING, rv);
4462
4463 rv = callback.WaitForResult();
4464 EXPECT_EQ(OK, rv);
4465
4466 const HttpResponseInfo* response = trans->GetResponseInfo();
4467 EXPECT_FALSE(response == NULL);
4468
4469 std::string response_text;
4470 rv = ReadTransaction(trans.get(), &response_text);
4471 EXPECT_EQ(OK, rv);
4472 EXPECT_EQ("Payload", response_text);
4473}
4474
4475TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094476 SessionDependencies session_deps(
4477 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354478
4479 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434480 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354481
4482 HttpRequestInfo request;
4483 request.method = "GET";
4484 request.url = GURL("http://www.google.com/");
4485 request.load_flags = 0;
4486
4487 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4488 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374489 const char kSOCKS5OkRequest[] = {
4490 0x05, // Version
4491 0x01, // Command (CONNECT)
4492 0x00, // Reserved.
4493 0x03, // Address type (DOMAINNAME).
4494 0x0E, // Length of domain (14)
4495 // Domain string:
4496 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4497 0x00, 0x50, // 16-bit port (80)
4498 };
[email protected]e0c27be2009-07-15 13:09:354499 const char kSOCKS5OkResponse[] =
4500 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4501
4502 MockWrite data_writes[] = {
4503 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4504 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4505 MockWrite("GET / HTTP/1.1\r\n"
4506 "Host: www.google.com\r\n"
4507 "Connection: keep-alive\r\n\r\n")
4508 };
4509
4510 MockRead data_reads[] = {
4511 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4512 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4513 MockRead("HTTP/1.0 200 OK\r\n"),
4514 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4515 MockRead("Payload"),
4516 MockRead(false, OK)
4517 };
4518
[email protected]31a2bfe2010-02-09 08:03:394519 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4520 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594521 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354522
4523 TestCompletionCallback callback;
4524
[email protected]5a1d7ca2010-04-28 20:12:274525 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354526 EXPECT_EQ(ERR_IO_PENDING, rv);
4527
4528 rv = callback.WaitForResult();
4529 EXPECT_EQ(OK, rv);
4530
4531 const HttpResponseInfo* response = trans->GetResponseInfo();
4532 EXPECT_FALSE(response == NULL);
4533
4534 std::string response_text;
4535 rv = ReadTransaction(trans.get(), &response_text);
4536 EXPECT_EQ(OK, rv);
4537 EXPECT_EQ("Payload", response_text);
4538}
4539
4540TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094541 SessionDependencies session_deps(
4542 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354543
4544 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434545 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354546
4547 HttpRequestInfo request;
4548 request.method = "GET";
4549 request.url = GURL("https://www.google.com/");
4550 request.load_flags = 0;
4551
4552 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4553 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374554 const unsigned char kSOCKS5OkRequest[] = {
4555 0x05, // Version
4556 0x01, // Command (CONNECT)
4557 0x00, // Reserved.
4558 0x03, // Address type (DOMAINNAME).
4559 0x0E, // Length of domain (14)
4560 // Domain string:
4561 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4562 0x01, 0xBB, // 16-bit port (443)
4563 };
4564
[email protected]e0c27be2009-07-15 13:09:354565 const char kSOCKS5OkResponse[] =
4566 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4567
4568 MockWrite data_writes[] = {
4569 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4570 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4571 arraysize(kSOCKS5OkRequest)),
4572 MockWrite("GET / HTTP/1.1\r\n"
4573 "Host: www.google.com\r\n"
4574 "Connection: keep-alive\r\n\r\n")
4575 };
4576
4577 MockRead data_reads[] = {
4578 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4579 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024580 MockRead("HTTP/1.0 200 OK\r\n"),
4581 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4582 MockRead("Payload"),
4583 MockRead(false, OK)
4584 };
4585
[email protected]31a2bfe2010-02-09 08:03:394586 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4587 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594588 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024589
[email protected]5ecc992a42009-11-11 01:41:594590 SSLSocketDataProvider ssl(true, OK);
4591 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024592
4593 TestCompletionCallback callback;
4594
[email protected]5a1d7ca2010-04-28 20:12:274595 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024596 EXPECT_EQ(ERR_IO_PENDING, rv);
4597
4598 rv = callback.WaitForResult();
4599 EXPECT_EQ(OK, rv);
4600
4601 const HttpResponseInfo* response = trans->GetResponseInfo();
4602 EXPECT_FALSE(response == NULL);
4603
4604 std::string response_text;
4605 rv = ReadTransaction(trans.get(), &response_text);
4606 EXPECT_EQ(OK, rv);
4607 EXPECT_EQ("Payload", response_text);
4608}
4609
[email protected]04e5be32009-06-26 20:00:314610// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064611
4612struct GroupNameTest {
4613 std::string proxy_server;
4614 std::string url;
4615 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184616 bool ssl;
[email protected]2d731a32010-04-29 01:04:064617};
4618
4619scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4620 const std::string& proxy_server) {
4621 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4622 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4623
4624 HttpAlternateProtocols* alternate_protocols =
4625 session->mutable_alternate_protocols();
4626 alternate_protocols->SetAlternateProtocolFor(
4627 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354628 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064629
4630 return session;
4631}
4632
4633int GroupNameTransactionHelper(
4634 const std::string& url,
4635 const scoped_refptr<HttpNetworkSession>& session) {
4636 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4637
4638 HttpRequestInfo request;
4639 request.method = "GET";
4640 request.url = GURL(url);
4641 request.load_flags = 0;
4642
4643 TestCompletionCallback callback;
4644
4645 // We do not complete this request, the dtor will clean the transaction up.
4646 return trans->Start(&request, &callback, BoundNetLog());
4647}
4648
4649TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4650 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314651 {
[email protected]2d731a32010-04-29 01:04:064652 "", // unused
[email protected]04e5be32009-06-26 20:00:314653 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544654 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184655 false,
[email protected]2ff8b312010-04-26 22:20:544656 },
4657 {
[email protected]2d731a32010-04-29 01:04:064658 "", // unused
[email protected]2ff8b312010-04-26 22:20:544659 "http://[2001:1418:13:1::25]/direct",
4660 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184661 false,
[email protected]04e5be32009-06-26 20:00:314662 },
[email protected]04e5be32009-06-26 20:00:314663
4664 // SSL Tests
4665 {
[email protected]2d731a32010-04-29 01:04:064666 "", // unused
[email protected]04e5be32009-06-26 20:00:314667 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024668 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184669 true,
[email protected]04e5be32009-06-26 20:00:314670 },
4671 {
[email protected]2d731a32010-04-29 01:04:064672 "", // unused
4673 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024674 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184675 true,
[email protected]04e5be32009-06-26 20:00:314676 },
4677 {
[email protected]2d731a32010-04-29 01:04:064678 "", // unused
[email protected]2ff8b312010-04-26 22:20:544679 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024680 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184681 true,
[email protected]2ff8b312010-04-26 22:20:544682 },
[email protected]2d731a32010-04-29 01:04:064683 };
[email protected]2ff8b312010-04-26 22:20:544684
[email protected]8e6441ca2010-08-19 05:56:384685 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064686
4687 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4688 scoped_refptr<HttpNetworkSession> session(
4689 SetupSessionForGroupNameTests(tests[i].proxy_server));
4690
4691 HttpNetworkSessionPeer peer(session);
4692 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4693 new CaptureGroupNameTCPSocketPool(session.get()));
4694 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184695 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4696 new CaptureGroupNameSSLSocketPool(session.get()));
4697 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064698
4699 EXPECT_EQ(ERR_IO_PENDING,
4700 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184701 if (tests[i].ssl)
4702 EXPECT_EQ(tests[i].expected_group_name,
4703 ssl_conn_pool->last_group_name_received());
4704 else
4705 EXPECT_EQ(tests[i].expected_group_name,
4706 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064707 }
4708
[email protected]8e6441ca2010-08-19 05:56:384709 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064710}
4711
4712TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4713 const GroupNameTest tests[] = {
4714 {
4715 "http_proxy",
4716 "http://www.google.com/http_proxy_normal",
4717 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184718 false,
[email protected]2d731a32010-04-29 01:04:064719 },
4720
4721 // SSL Tests
4722 {
4723 "http_proxy",
4724 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024725 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184726 true,
[email protected]2d731a32010-04-29 01:04:064727 },
4728
[email protected]9faeded92010-04-29 20:03:054729 {
4730 "http_proxy",
4731 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024732 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184733 true,
[email protected]9faeded92010-04-29 20:03:054734 },
[email protected]2d731a32010-04-29 01:04:064735 };
4736
[email protected]8e6441ca2010-08-19 05:56:384737 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064738
4739 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4740 scoped_refptr<HttpNetworkSession> session(
4741 SetupSessionForGroupNameTests(tests[i].proxy_server));
4742
4743 HttpNetworkSessionPeer peer(session);
4744
[email protected]e60e47a2010-07-14 03:37:184745 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134746 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4747 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184748 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4749 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4750 new CaptureGroupNameSSLSocketPool(session.get()));
4751 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064752
4753 EXPECT_EQ(ERR_IO_PENDING,
4754 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184755 if (tests[i].ssl)
4756 EXPECT_EQ(tests[i].expected_group_name,
4757 ssl_conn_pool->last_group_name_received());
4758 else
4759 EXPECT_EQ(tests[i].expected_group_name,
4760 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064761 }
4762
[email protected]8e6441ca2010-08-19 05:56:384763 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064764}
4765
4766TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4767 const GroupNameTest tests[] = {
4768 {
4769 "socks4://socks_proxy:1080",
4770 "http://www.google.com/socks4_direct",
4771 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184772 false,
[email protected]2d731a32010-04-29 01:04:064773 },
4774 {
4775 "socks5://socks_proxy:1080",
4776 "http://www.google.com/socks5_direct",
4777 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184778 false,
[email protected]2d731a32010-04-29 01:04:064779 },
4780
4781 // SSL Tests
4782 {
4783 "socks4://socks_proxy:1080",
4784 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024785 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184786 true,
[email protected]2d731a32010-04-29 01:04:064787 },
4788 {
4789 "socks5://socks_proxy:1080",
4790 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024791 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184792 true,
[email protected]2d731a32010-04-29 01:04:064793 },
4794
[email protected]9faeded92010-04-29 20:03:054795 {
4796 "socks4://socks_proxy:1080",
4797 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024798 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184799 true,
[email protected]9faeded92010-04-29 20:03:054800 },
[email protected]04e5be32009-06-26 20:00:314801 };
4802
[email protected]8e6441ca2010-08-19 05:56:384803 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:544804
[email protected]04e5be32009-06-26 20:00:314805 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064806 scoped_refptr<HttpNetworkSession> session(
4807 SetupSessionForGroupNameTests(tests[i].proxy_server));
4808 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314809
[email protected]e60e47a2010-07-14 03:37:184810 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264811 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064812 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184813 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4814 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4815 new CaptureGroupNameSSLSocketPool(session.get()));
4816 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314817
[email protected]5695b8c2009-09-30 21:36:434818 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314819
[email protected]2d731a32010-04-29 01:04:064820 EXPECT_EQ(ERR_IO_PENDING,
4821 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184822 if (tests[i].ssl)
4823 EXPECT_EQ(tests[i].expected_group_name,
4824 ssl_conn_pool->last_group_name_received());
4825 else
4826 EXPECT_EQ(tests[i].expected_group_name,
4827 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314828 }
[email protected]2ff8b312010-04-26 22:20:544829
[email protected]8e6441ca2010-08-19 05:56:384830 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:314831}
4832
[email protected]9172a982009-06-06 00:30:254833TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544834 SessionDependencies session_deps(
4835 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324836
[email protected]69719062010-01-05 20:09:214837 // This simulates failure resolving all hostnames; that means we will fail
4838 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324839 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4840
[email protected]9172a982009-06-06 00:30:254841 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434842 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254843
4844 HttpRequestInfo request;
4845 request.method = "GET";
4846 request.url = GURL("http://www.google.com/");
4847
4848 TestCompletionCallback callback;
4849
[email protected]5a1d7ca2010-04-28 20:12:274850 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254851 EXPECT_EQ(ERR_IO_PENDING, rv);
4852
[email protected]9172a982009-06-06 00:30:254853 rv = callback.WaitForResult();
4854 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4855}
4856
[email protected]f3e6c1e2009-06-15 20:52:124857// Host resolution observer used by
4858// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4859// resovle requests are issued with a referrer of |expected_referrer|.
4860class ResolutionReferrerObserver : public HostResolver::Observer {
4861 public:
4862 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4863 : expected_referrer_(expected_referrer),
4864 called_start_with_referrer_(false),
4865 called_finish_with_referrer_(false) {
4866 }
4867
4868 virtual void OnStartResolution(int id,
4869 const HostResolver::RequestInfo& info) {
4870 if (info.referrer() == expected_referrer_)
4871 called_start_with_referrer_ = true;
4872 }
4873
4874 virtual void OnFinishResolutionWithStatus(
4875 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4876 if (info.referrer() == expected_referrer_)
4877 called_finish_with_referrer_ = true;
4878 }
4879
[email protected]eb255d32009-06-17 02:11:034880 virtual void OnCancelResolution(int id,
4881 const HostResolver::RequestInfo& info ) {
4882 FAIL() << "Should not be cancelling any requests!";
4883 }
4884
[email protected]f3e6c1e2009-06-15 20:52:124885 bool did_complete_with_expected_referrer() const {
4886 return called_start_with_referrer_ && called_finish_with_referrer_;
4887 }
4888
4889 private:
4890 GURL expected_referrer_;
4891 bool called_start_with_referrer_;
4892 bool called_finish_with_referrer_;
4893
4894 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4895};
4896
4897// Make sure that when HostResolver::Resolve() is invoked, it passes through
4898// the "referrer". This is depended on by the DNS prefetch observer.
4899TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4900 GURL referrer = GURL("http://expected-referrer/");
4901 EXPECT_TRUE(referrer.is_valid());
4902 ResolutionReferrerObserver resolution_observer(referrer);
4903
4904 SessionDependencies session_deps;
4905 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434906 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124907
4908 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144909 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124910
4911 // Connect up a mock socket which will fail when reading.
4912 MockRead data_reads[] = {
4913 MockRead(false, ERR_FAILED),
4914 };
[email protected]31a2bfe2010-02-09 08:03:394915 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594916 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124917
4918 // Issue a request, containing an HTTP referrer.
4919 HttpRequestInfo request;
4920 request.method = "GET";
4921 request.referrer = referrer;
4922 request.url = GURL("http://www.google.com/");
4923
4924 // Run the request until it fails reading from the socket.
4925 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274926 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124927 EXPECT_EQ(ERR_IO_PENDING, rv);
4928 rv = callback.WaitForResult();
4929 EXPECT_EQ(ERR_FAILED, rv);
4930
4931 // Check that the host resolution observer saw |referrer|.
4932 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4933}
4934
[email protected]685af592010-05-11 19:31:244935// Base test to make sure that when the load flags for a request specify to
4936// bypass the cache, the DNS cache is not used.
4937void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284938 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324939
[email protected]a2c2fb92009-07-18 07:31:044940 // Select a host resolver that does caching.
4941 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324942
[email protected]3b9cca42009-06-16 01:08:284943 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434944 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284945
4946 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4947 // a synchronous lookup.)
4948 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144949 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464950 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274951 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284952 EXPECT_EQ(OK, rv);
4953
4954 // Verify that it was added to host cache, by doing a subsequent async lookup
4955 // and confirming it completes synchronously.
4956 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464957 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284958 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274959 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324960 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284961
4962 // Inject a failure the next time that "www.google.com" is resolved. This way
4963 // we can tell if the next lookup hit the cache, or the "network".
4964 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324965 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284966
4967 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4968 // first read -- this won't be reached as the host resolution will fail first.
4969 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394970 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594971 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284972
4973 // Issue a request, asking to bypass the cache(s).
4974 HttpRequestInfo request;
4975 request.method = "GET";
[email protected]685af592010-05-11 19:31:244976 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284977 request.url = GURL("http://www.google.com/");
4978
4979 // Run the request.
4980 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274981 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284982 ASSERT_EQ(ERR_IO_PENDING, rv);
4983 rv = callback.WaitForResult();
4984
4985 // If we bypassed the cache, we would have gotten a failure while resolving
4986 // "www.google.com".
4987 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4988}
4989
[email protected]685af592010-05-11 19:31:244990// There are multiple load flags that should trigger the host cache bypass.
4991// Test each in isolation:
4992TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4993 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4994}
4995
4996TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4997 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4998}
4999
5000TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5001 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5002}
5003
[email protected]0877e3d2009-10-17 22:29:575004// Make sure we can handle an error when writing the request.
5005TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5006 SessionDependencies session_deps;
5007 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5008
5009 HttpRequestInfo request;
5010 request.method = "GET";
5011 request.url = GURL("http://www.foo.com/");
5012 request.load_flags = 0;
5013
5014 MockWrite write_failure[] = {
5015 MockWrite(true, ERR_CONNECTION_RESET),
5016 };
[email protected]31a2bfe2010-02-09 08:03:395017 StaticSocketDataProvider data(NULL, 0,
5018 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595019 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575020
5021 TestCompletionCallback callback;
5022
5023 scoped_ptr<HttpTransaction> trans(
5024 new HttpNetworkTransaction(CreateSession(&session_deps)));
5025
[email protected]5a1d7ca2010-04-28 20:12:275026 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575027 EXPECT_EQ(ERR_IO_PENDING, rv);
5028
5029 rv = callback.WaitForResult();
5030 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5031}
5032
5033// Check that a connection closed after the start of the headers finishes ok.
5034TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5035 SessionDependencies session_deps;
5036 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5037
5038 HttpRequestInfo request;
5039 request.method = "GET";
5040 request.url = GURL("http://www.foo.com/");
5041 request.load_flags = 0;
5042
5043 MockRead data_reads[] = {
5044 MockRead("HTTP/1."),
5045 MockRead(false, OK),
5046 };
5047
[email protected]31a2bfe2010-02-09 08:03:395048 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595049 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575050
5051 TestCompletionCallback callback;
5052
5053 scoped_ptr<HttpTransaction> trans(
5054 new HttpNetworkTransaction(CreateSession(&session_deps)));
5055
[email protected]5a1d7ca2010-04-28 20:12:275056 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575057 EXPECT_EQ(ERR_IO_PENDING, rv);
5058
5059 rv = callback.WaitForResult();
5060 EXPECT_EQ(OK, rv);
5061
5062 const HttpResponseInfo* response = trans->GetResponseInfo();
5063 EXPECT_TRUE(response != NULL);
5064
5065 EXPECT_TRUE(response->headers != NULL);
5066 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5067
5068 std::string response_data;
5069 rv = ReadTransaction(trans.get(), &response_data);
5070 EXPECT_EQ(OK, rv);
5071 EXPECT_EQ("", response_data);
5072}
5073
5074// Make sure that a dropped connection while draining the body for auth
5075// restart does the right thing.
5076TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5077 SessionDependencies session_deps;
5078 scoped_ptr<HttpTransaction> trans(
5079 new HttpNetworkTransaction(CreateSession(&session_deps)));
5080
5081 HttpRequestInfo request;
5082 request.method = "GET";
5083 request.url = GURL("http://www.google.com/");
5084 request.load_flags = 0;
5085
5086 MockWrite data_writes1[] = {
5087 MockWrite("GET / HTTP/1.1\r\n"
5088 "Host: www.google.com\r\n"
5089 "Connection: keep-alive\r\n\r\n"),
5090 };
5091
5092 MockRead data_reads1[] = {
5093 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5094 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5095 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5096 MockRead("Content-Length: 14\r\n\r\n"),
5097 MockRead("Unauth"),
5098 MockRead(true, ERR_CONNECTION_RESET),
5099 };
5100
[email protected]31a2bfe2010-02-09 08:03:395101 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5102 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595103 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575104
5105 // After calling trans->RestartWithAuth(), this is the request we should
5106 // be issuing -- the final header line contains the credentials.
5107 MockWrite data_writes2[] = {
5108 MockWrite("GET / HTTP/1.1\r\n"
5109 "Host: www.google.com\r\n"
5110 "Connection: keep-alive\r\n"
5111 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5112 };
5113
5114 // Lastly, the server responds with the actual content.
5115 MockRead data_reads2[] = {
5116 MockRead("HTTP/1.1 200 OK\r\n"),
5117 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5118 MockRead("Content-Length: 100\r\n\r\n"),
5119 MockRead(false, OK),
5120 };
5121
[email protected]31a2bfe2010-02-09 08:03:395122 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5123 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595124 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575125
5126 TestCompletionCallback callback1;
5127
[email protected]5a1d7ca2010-04-28 20:12:275128 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575129 EXPECT_EQ(ERR_IO_PENDING, rv);
5130
5131 rv = callback1.WaitForResult();
5132 EXPECT_EQ(OK, rv);
5133
5134 const HttpResponseInfo* response = trans->GetResponseInfo();
5135 EXPECT_FALSE(response == NULL);
5136
5137 // The password prompt info should have been set in response->auth_challenge.
5138 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5139
5140 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5141 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5142 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5143
5144 TestCompletionCallback callback2;
5145
[email protected]13c8a092010-07-29 06:15:445146 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575147 EXPECT_EQ(ERR_IO_PENDING, rv);
5148
5149 rv = callback2.WaitForResult();
5150 EXPECT_EQ(OK, rv);
5151
5152 response = trans->GetResponseInfo();
5153 EXPECT_FALSE(response == NULL);
5154 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5155 EXPECT_EQ(100, response->headers->GetContentLength());
5156}
5157
5158// Test HTTPS connections going through a proxy that sends extra data.
5159TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
5160 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
5161
5162 HttpRequestInfo request;
5163 request.method = "GET";
5164 request.url = GURL("https://www.google.com/");
5165 request.load_flags = 0;
5166
5167 MockRead proxy_reads[] = {
5168 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5169 MockRead(false, OK)
5170 };
5171
[email protected]31a2bfe2010-02-09 08:03:395172 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595173 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575174
[email protected]5ecc992a42009-11-11 01:41:595175 session_deps.socket_factory.AddSocketDataProvider(&data);
5176 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575177
5178 TestCompletionCallback callback;
5179
5180 session_deps.socket_factory.ResetNextMockIndexes();
5181
5182 scoped_ptr<HttpTransaction> trans(
5183 new HttpNetworkTransaction(CreateSession(&session_deps)));
5184
[email protected]5a1d7ca2010-04-28 20:12:275185 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575186 EXPECT_EQ(ERR_IO_PENDING, rv);
5187
5188 rv = callback.WaitForResult();
5189 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5190}
5191
[email protected]e22e1362009-11-23 21:31:125192TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465193 SessionDependencies session_deps;
5194 scoped_ptr<HttpTransaction> trans(
5195 new HttpNetworkTransaction(CreateSession(&session_deps)));
5196
5197 HttpRequestInfo request;
5198 request.method = "GET";
5199 request.url = GURL("http://www.google.com/");
5200 request.load_flags = 0;
5201
[email protected]e22e1362009-11-23 21:31:125202 MockRead data_reads[] = {
5203 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5204 MockRead(false, OK),
5205 };
[email protected]9492e4a2010-02-24 00:58:465206
5207 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5208 session_deps.socket_factory.AddSocketDataProvider(&data);
5209
5210 TestCompletionCallback callback;
5211
[email protected]5a1d7ca2010-04-28 20:12:275212 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465213 EXPECT_EQ(ERR_IO_PENDING, rv);
5214
5215 EXPECT_EQ(OK, callback.WaitForResult());
5216
5217 const HttpResponseInfo* response = trans->GetResponseInfo();
5218 EXPECT_TRUE(response != NULL);
5219
5220 EXPECT_TRUE(response->headers != NULL);
5221 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5222
5223 std::string response_data;
5224 rv = ReadTransaction(trans.get(), &response_data);
5225 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125226}
5227
[email protected]95d88ffe2010-02-04 21:25:335228TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5229 SessionDependencies session_deps;
5230 scoped_ptr<HttpTransaction> trans(
5231 new HttpNetworkTransaction(CreateSession(&session_deps)));
5232
5233 HttpRequestInfo request;
5234 request.method = "POST";
5235 request.url = GURL("http://www.google.com/upload");
5236 request.upload_data = new UploadData;
5237 request.load_flags = 0;
5238
5239 FilePath temp_file_path;
5240 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5241 const uint64 kFakeSize = 100000; // file is actually blank
5242
5243 std::vector<UploadData::Element> elements;
5244 UploadData::Element element;
5245 element.SetToFilePath(temp_file_path);
5246 element.SetContentLength(kFakeSize);
5247 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535248 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335249 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5250
5251 MockRead data_reads[] = {
5252 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5253 MockRead("hello world"),
5254 MockRead(false, OK),
5255 };
[email protected]31a2bfe2010-02-09 08:03:395256 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335257 session_deps.socket_factory.AddSocketDataProvider(&data);
5258
5259 TestCompletionCallback callback;
5260
[email protected]5a1d7ca2010-04-28 20:12:275261 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335262 EXPECT_EQ(ERR_IO_PENDING, rv);
5263
5264 rv = callback.WaitForResult();
5265 EXPECT_EQ(OK, rv);
5266
5267 const HttpResponseInfo* response = trans->GetResponseInfo();
5268 EXPECT_TRUE(response != NULL);
5269
5270 EXPECT_TRUE(response->headers != NULL);
5271 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5272
5273 std::string response_data;
5274 rv = ReadTransaction(trans.get(), &response_data);
5275 EXPECT_EQ(OK, rv);
5276 EXPECT_EQ("hello world", response_data);
5277
5278 file_util::Delete(temp_file_path, false);
5279}
5280
[email protected]6624b4622010-03-29 19:58:365281TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5282 // If we try to upload an unreadable file, the network stack should report
5283 // the file size as zero and upload zero bytes for that file.
5284 SessionDependencies session_deps;
5285 scoped_ptr<HttpTransaction> trans(
5286 new HttpNetworkTransaction(CreateSession(&session_deps)));
5287
5288 FilePath temp_file;
5289 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5290 std::string temp_file_content("Unreadable file.");
5291 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5292 temp_file_content.length()));
5293 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5294
5295 HttpRequestInfo request;
5296 request.method = "POST";
5297 request.url = GURL("http://www.google.com/upload");
5298 request.upload_data = new UploadData;
5299 request.load_flags = 0;
5300
5301 std::vector<UploadData::Element> elements;
5302 UploadData::Element element;
5303 element.SetToFilePath(temp_file);
5304 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535305 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365306
5307 MockRead data_reads[] = {
5308 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5309 MockRead(false, OK),
5310 };
5311 MockWrite data_writes[] = {
5312 MockWrite("POST /upload HTTP/1.1\r\n"
5313 "Host: www.google.com\r\n"
5314 "Connection: keep-alive\r\n"
5315 "Content-Length: 0\r\n\r\n"),
5316 MockWrite(false, OK),
5317 };
5318 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5319 arraysize(data_writes));
5320 session_deps.socket_factory.AddSocketDataProvider(&data);
5321
5322 TestCompletionCallback callback;
5323
[email protected]5a1d7ca2010-04-28 20:12:275324 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365325 EXPECT_EQ(ERR_IO_PENDING, rv);
5326
5327 rv = callback.WaitForResult();
5328 EXPECT_EQ(OK, rv);
5329
5330 const HttpResponseInfo* response = trans->GetResponseInfo();
5331 EXPECT_TRUE(response != NULL);
5332 EXPECT_TRUE(response->headers != NULL);
5333 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5334
5335 file_util::Delete(temp_file, false);
5336}
5337
5338TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5339 SessionDependencies session_deps;
5340 scoped_ptr<HttpTransaction> trans(
5341 new HttpNetworkTransaction(CreateSession(&session_deps)));
5342
5343 FilePath temp_file;
5344 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5345 std::string temp_file_contents("Unreadable file.");
5346 std::string unreadable_contents(temp_file_contents.length(), '\0');
5347 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5348 temp_file_contents.length()));
5349
5350 HttpRequestInfo request;
5351 request.method = "POST";
5352 request.url = GURL("http://www.google.com/upload");
5353 request.upload_data = new UploadData;
5354 request.load_flags = 0;
5355
5356 std::vector<UploadData::Element> elements;
5357 UploadData::Element element;
5358 element.SetToFilePath(temp_file);
5359 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535360 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365361
5362 MockRead data_reads[] = {
5363 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5364 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5365 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5366
5367 MockRead("HTTP/1.1 200 OK\r\n"),
5368 MockRead("Content-Length: 0\r\n\r\n"),
5369 MockRead(false, OK),
5370 };
5371 MockWrite data_writes[] = {
5372 MockWrite("POST /upload HTTP/1.1\r\n"
5373 "Host: www.google.com\r\n"
5374 "Connection: keep-alive\r\n"
5375 "Content-Length: 16\r\n\r\n"),
5376 MockWrite(false, temp_file_contents.c_str()),
5377
5378 MockWrite("POST /upload HTTP/1.1\r\n"
5379 "Host: www.google.com\r\n"
5380 "Connection: keep-alive\r\n"
5381 "Content-Length: 16\r\n"
5382 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5383 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5384 MockWrite(false, OK),
5385 };
5386 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5387 arraysize(data_writes));
5388 session_deps.socket_factory.AddSocketDataProvider(&data);
5389
5390 TestCompletionCallback callback1;
5391
[email protected]5a1d7ca2010-04-28 20:12:275392 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365393 EXPECT_EQ(ERR_IO_PENDING, rv);
5394
5395 rv = callback1.WaitForResult();
5396 EXPECT_EQ(OK, rv);
5397
5398 const HttpResponseInfo* response = trans->GetResponseInfo();
5399 EXPECT_TRUE(response != NULL);
5400 EXPECT_TRUE(response->headers != NULL);
5401 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5402
5403 // The password prompt info should have been set in response->auth_challenge.
5404 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5405 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5406 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5407 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5408
5409 // Now make the file unreadable and try again.
5410 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5411
5412 TestCompletionCallback callback2;
5413
[email protected]13c8a092010-07-29 06:15:445414 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365415 EXPECT_EQ(ERR_IO_PENDING, rv);
5416
5417 rv = callback2.WaitForResult();
5418 EXPECT_EQ(OK, rv);
5419
5420 response = trans->GetResponseInfo();
5421 EXPECT_TRUE(response != NULL);
5422 EXPECT_TRUE(response->headers != NULL);
5423 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5424 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5425
5426 file_util::Delete(temp_file, false);
5427}
5428
[email protected]aeefc9e82010-02-19 16:18:275429// Tests that changes to Auth realms are treated like auth rejections.
5430TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5431 SessionDependencies session_deps;
5432 scoped_ptr<HttpTransaction> trans(
5433 new HttpNetworkTransaction(CreateSession(&session_deps)));
5434
5435 HttpRequestInfo request;
5436 request.method = "GET";
5437 request.url = GURL("http://www.google.com/");
5438 request.load_flags = 0;
5439
5440 // First transaction will request a resource and receive a Basic challenge
5441 // with realm="first_realm".
5442 MockWrite data_writes1[] = {
5443 MockWrite("GET / HTTP/1.1\r\n"
5444 "Host: www.google.com\r\n"
5445 "Connection: keep-alive\r\n"
5446 "\r\n"),
5447 };
5448 MockRead data_reads1[] = {
5449 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5450 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5451 "\r\n"),
5452 };
5453
5454 // After calling trans->RestartWithAuth(), provide an Authentication header
5455 // for first_realm. The server will reject and provide a challenge with
5456 // second_realm.
5457 MockWrite data_writes2[] = {
5458 MockWrite("GET / HTTP/1.1\r\n"
5459 "Host: www.google.com\r\n"
5460 "Connection: keep-alive\r\n"
5461 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5462 "\r\n"),
5463 };
5464 MockRead data_reads2[] = {
5465 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5466 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5467 "\r\n"),
5468 };
5469
5470 // This again fails, and goes back to first_realm. Make sure that the
5471 // entry is removed from cache.
5472 MockWrite data_writes3[] = {
5473 MockWrite("GET / HTTP/1.1\r\n"
5474 "Host: www.google.com\r\n"
5475 "Connection: keep-alive\r\n"
5476 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5477 "\r\n"),
5478 };
5479 MockRead data_reads3[] = {
5480 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5481 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5482 "\r\n"),
5483 };
5484
5485 // Try one last time (with the correct password) and get the resource.
5486 MockWrite data_writes4[] = {
5487 MockWrite("GET / HTTP/1.1\r\n"
5488 "Host: www.google.com\r\n"
5489 "Connection: keep-alive\r\n"
5490 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5491 "\r\n"),
5492 };
5493 MockRead data_reads4[] = {
5494 MockRead("HTTP/1.1 200 OK\r\n"
5495 "Content-Type: text/html; charset=iso-8859-1\r\n"
5496 "Content-Length: 100\r\n"
5497 "\r\n"),
5498 };
5499
5500 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5501 data_writes1, arraysize(data_writes1));
5502 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5503 data_writes2, arraysize(data_writes2));
5504 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5505 data_writes3, arraysize(data_writes3));
5506 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5507 data_writes4, arraysize(data_writes4));
5508 session_deps.socket_factory.AddSocketDataProvider(&data1);
5509 session_deps.socket_factory.AddSocketDataProvider(&data2);
5510 session_deps.socket_factory.AddSocketDataProvider(&data3);
5511 session_deps.socket_factory.AddSocketDataProvider(&data4);
5512
5513 TestCompletionCallback callback1;
5514
5515 // Issue the first request with Authorize headers. There should be a
5516 // password prompt for first_realm waiting to be filled in after the
5517 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275518 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275519 EXPECT_EQ(ERR_IO_PENDING, rv);
5520 rv = callback1.WaitForResult();
5521 EXPECT_EQ(OK, rv);
5522 const HttpResponseInfo* response = trans->GetResponseInfo();
5523 ASSERT_FALSE(response == NULL);
5524 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5525 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5526 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5527 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5528
5529 // Issue the second request with an incorrect password. There should be a
5530 // password prompt for second_realm waiting to be filled in after the
5531 // transaction completes.
5532 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445533 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275534 EXPECT_EQ(ERR_IO_PENDING, rv);
5535 rv = callback2.WaitForResult();
5536 EXPECT_EQ(OK, rv);
5537 response = trans->GetResponseInfo();
5538 ASSERT_FALSE(response == NULL);
5539 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5540 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5541 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5542 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5543
5544 // Issue the third request with another incorrect password. There should be
5545 // a password prompt for first_realm waiting to be filled in. If the password
5546 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5547 // first_realm was not correctly removed.
5548 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445549 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275550 EXPECT_EQ(ERR_IO_PENDING, rv);
5551 rv = callback3.WaitForResult();
5552 EXPECT_EQ(OK, rv);
5553 response = trans->GetResponseInfo();
5554 ASSERT_FALSE(response == NULL);
5555 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5556 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5557 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5558 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5559
5560 // Issue the fourth request with the correct password and username.
5561 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445562 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275563 EXPECT_EQ(ERR_IO_PENDING, rv);
5564 rv = callback4.WaitForResult();
5565 EXPECT_EQ(OK, rv);
5566 response = trans->GetResponseInfo();
5567 ASSERT_FALSE(response == NULL);
5568 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5569}
5570
[email protected]564b4912010-03-09 16:30:425571TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:385572 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
5573 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:425574
[email protected]564b4912010-03-09 16:30:425575 SessionDependencies session_deps;
5576
5577 MockRead data_reads[] = {
5578 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355579 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425580 MockRead("hello world"),
5581 MockRead(false, OK),
5582 };
5583
5584 HttpRequestInfo request;
5585 request.method = "GET";
5586 request.url = GURL("http://www.google.com/");
5587 request.load_flags = 0;
5588
5589 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5590
5591 session_deps.socket_factory.AddSocketDataProvider(&data);
5592
5593 TestCompletionCallback callback;
5594
5595 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5596 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5597
[email protected]5a1d7ca2010-04-28 20:12:275598 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425599 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535600
[email protected]2fbaecf22010-07-22 22:20:355601 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425602 const HttpAlternateProtocols& alternate_protocols =
5603 session->alternate_protocols();
5604 EXPECT_FALSE(
5605 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5606
5607 EXPECT_EQ(OK, callback.WaitForResult());
5608
5609 const HttpResponseInfo* response = trans->GetResponseInfo();
5610 ASSERT_TRUE(response != NULL);
5611 ASSERT_TRUE(response->headers != NULL);
5612 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535613 EXPECT_FALSE(response->was_fetched_via_spdy);
5614 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575615 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425616
5617 std::string response_data;
5618 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5619 EXPECT_EQ("hello world", response_data);
5620
5621 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5622 const HttpAlternateProtocols::PortProtocolPair alternate =
5623 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5624 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5625 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355626 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425627 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425628
[email protected]8e6441ca2010-08-19 05:56:385629 HttpStreamFactory::set_use_alternate_protocols(false);
5630 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:425631}
5632
5633TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:385634 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:425635 SessionDependencies session_deps;
5636
5637 HttpRequestInfo request;
5638 request.method = "GET";
5639 request.url = GURL("http://www.google.com/");
5640 request.load_flags = 0;
5641
5642 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5643 StaticSocketDataProvider first_data;
5644 first_data.set_connect_data(mock_connect);
5645 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5646
5647 MockRead data_reads[] = {
5648 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5649 MockRead("hello world"),
5650 MockRead(true, OK),
5651 };
5652 StaticSocketDataProvider second_data(
5653 data_reads, arraysize(data_reads), NULL, 0);
5654 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5655
5656 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5657 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5658 // http://crbug.com/37454.
5659 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5660
5661 TestCompletionCallback callback;
5662
5663 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5664
[email protected]2fbaecf22010-07-22 22:20:355665 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425666 HttpAlternateProtocols* alternate_protocols =
5667 session->mutable_alternate_protocols();
5668 alternate_protocols->SetAlternateProtocolFor(
5669 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355670 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425671
5672 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5673
[email protected]5a1d7ca2010-04-28 20:12:275674 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425675 EXPECT_EQ(ERR_IO_PENDING, rv);
5676 EXPECT_EQ(OK, callback.WaitForResult());
5677
5678 const HttpResponseInfo* response = trans->GetResponseInfo();
5679 ASSERT_TRUE(response != NULL);
5680 ASSERT_TRUE(response->headers != NULL);
5681 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5682
5683 std::string response_data;
5684 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5685 EXPECT_EQ("hello world", response_data);
5686
5687 ASSERT_TRUE(
5688 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5689 const HttpAlternateProtocols::PortProtocolPair alternate =
5690 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5691 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:385692 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:425693}
5694
5695// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5696// says that it does SPDY, but it just does the TLS handshake, but the NPN
5697// response does not indicate SPDY, so we just do standard HTTPS over the port.
5698// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5699// on the original port.
[email protected]a2cb8122010-03-10 17:22:425700// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5701// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535702//
[email protected]a2cb8122010-03-10 17:22:425703// HttpRequestInfo request;
5704// request.method = "GET";
5705// request.url = GURL("http://www.google.com/");
5706// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535707//
[email protected]a2cb8122010-03-10 17:22:425708// MockRead data_reads[] = {
5709// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5710// MockRead("hello world"),
5711// MockRead(true, OK),
5712// };
5713// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5714// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535715//
[email protected]a2cb8122010-03-10 17:22:425716// SSLSocketDataProvider ssl(true, OK);
5717// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535718//
[email protected]a2cb8122010-03-10 17:22:425719// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535720//
[email protected]a2cb8122010-03-10 17:22:425721// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535722//
[email protected]a2cb8122010-03-10 17:22:425723// HostPortPair http_host_port_pair;
5724// http_host_port_pair.host = "www.google.com";
5725// http_host_port_pair.port = 80;
5726// HttpAlternateProtocols* alternate_protocols =
5727// session->mutable_alternate_protocols();
5728// alternate_protocols->SetAlternateProtocolFor(
5729// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065730// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535731//
[email protected]a2cb8122010-03-10 17:22:425732// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535733//
[email protected]5a1d7ca2010-04-28 20:12:275734// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425735// EXPECT_EQ(ERR_IO_PENDING, rv);
5736// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535737//
[email protected]a2cb8122010-03-10 17:22:425738// const HttpResponseInfo* response = trans->GetResponseInfo();
5739// ASSERT_TRUE(response != NULL);
5740// ASSERT_TRUE(response->headers != NULL);
5741// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535742//
[email protected]a2cb8122010-03-10 17:22:425743// std::string response_data;
5744// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5745// EXPECT_EQ("hello world", response_data);
5746// }
5747
5748TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:385749 HttpStreamFactory::set_use_alternate_protocols(true);
5750 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425751 SessionDependencies session_deps;
5752
5753 HttpRequestInfo request;
5754 request.method = "GET";
5755 request.url = GURL("http://www.google.com/");
5756 request.load_flags = 0;
5757
[email protected]a2cb8122010-03-10 17:22:425758 StaticSocketDataProvider first_tcp_connect;
5759 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5760
5761 SSLSocketDataProvider ssl(true, OK);
5762 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5763
[email protected]564b4912010-03-09 16:30:425764 MockRead data_reads[] = {
5765 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5766 MockRead("hello world"),
5767 MockRead(true, OK),
5768 };
[email protected]a2cb8122010-03-10 17:22:425769 StaticSocketDataProvider fallback_data(
5770 data_reads, arraysize(data_reads), NULL, 0);
5771 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425772
5773 TestCompletionCallback callback;
5774
5775 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5776
[email protected]2fbaecf22010-07-22 22:20:355777 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425778 HttpAlternateProtocols* alternate_protocols =
5779 session->mutable_alternate_protocols();
5780 alternate_protocols->SetAlternateProtocolFor(
5781 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355782 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425783
5784 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5785
[email protected]5a1d7ca2010-04-28 20:12:275786 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425787 EXPECT_EQ(ERR_IO_PENDING, rv);
5788 EXPECT_EQ(OK, callback.WaitForResult());
5789
5790 const HttpResponseInfo* response = trans->GetResponseInfo();
5791 ASSERT_TRUE(response != NULL);
5792 ASSERT_TRUE(response->headers != NULL);
5793 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5794
5795 std::string response_data;
5796 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5797 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:385798 HttpStreamFactory::set_next_protos("");
5799 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:545800}
5801
5802TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:385803 HttpStreamFactory::set_use_alternate_protocols(true);
5804 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545805 SessionDependencies session_deps;
5806
5807 HttpRequestInfo request;
5808 request.method = "GET";
5809 request.url = GURL("http://www.google.com/");
5810 request.load_flags = 0;
5811
5812 MockRead data_reads[] = {
5813 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355814 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545815 MockRead("hello world"),
5816 MockRead(true, OK),
5817 };
5818
5819 StaticSocketDataProvider first_transaction(
5820 data_reads, arraysize(data_reads), NULL, 0);
5821 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5822
5823 SSLSocketDataProvider ssl(true, OK);
5824 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355825 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535826 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545827 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5828
[email protected]2bd93022010-07-17 00:58:445829 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135830 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545831
[email protected]2bd93022010-07-17 00:58:445832 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5833 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545834 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135835 CreateMockRead(*resp),
5836 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545837 MockRead(true, 0, 0),
5838 };
5839
5840 scoped_refptr<DelayedSocketData> spdy_data(
5841 new DelayedSocketData(
5842 1, // wait for one write to finish before reading.
5843 spdy_reads, arraysize(spdy_reads),
5844 spdy_writes, arraysize(spdy_writes)));
5845 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5846
5847 TestCompletionCallback callback;
5848
5849 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5850 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5851
[email protected]5a1d7ca2010-04-28 20:12:275852 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545853 EXPECT_EQ(ERR_IO_PENDING, rv);
5854 EXPECT_EQ(OK, callback.WaitForResult());
5855
5856 const HttpResponseInfo* response = trans->GetResponseInfo();
5857 ASSERT_TRUE(response != NULL);
5858 ASSERT_TRUE(response->headers != NULL);
5859 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5860
5861 std::string response_data;
5862 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5863 EXPECT_EQ("hello world", response_data);
5864
5865 trans.reset(new HttpNetworkTransaction(session));
5866
[email protected]5a1d7ca2010-04-28 20:12:275867 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545868 EXPECT_EQ(ERR_IO_PENDING, rv);
5869 EXPECT_EQ(OK, callback.WaitForResult());
5870
5871 response = trans->GetResponseInfo();
5872 ASSERT_TRUE(response != NULL);
5873 ASSERT_TRUE(response->headers != NULL);
5874 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535875 EXPECT_TRUE(response->was_fetched_via_spdy);
5876 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575877 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545878
5879 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5880 EXPECT_EQ("hello!", response_data);
5881
[email protected]8e6441ca2010-08-19 05:56:385882 HttpStreamFactory::set_next_protos("");
5883 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:545884}
5885
[email protected]631f1322010-04-30 17:59:115886class CapturingProxyResolver : public ProxyResolver {
5887 public:
5888 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5889 virtual ~CapturingProxyResolver() {}
5890
5891 virtual int GetProxyForURL(const GURL& url,
5892 ProxyInfo* results,
5893 CompletionCallback* callback,
5894 RequestHandle* request,
5895 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:405896 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
5897 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:425898 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115899 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425900 return OK;
[email protected]631f1322010-04-30 17:59:115901 }
5902
5903 virtual void CancelRequest(RequestHandle request) {
5904 NOTREACHED();
5905 }
5906
[email protected]24476402010-07-20 20:55:175907 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:115908 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425909 return OK;
[email protected]631f1322010-04-30 17:59:115910 }
5911
[email protected]24476402010-07-20 20:55:175912 const std::vector<GURL>& resolved() const { return resolved_; }
5913
5914 private:
[email protected]631f1322010-04-30 17:59:115915 std::vector<GURL> resolved_;
5916
5917 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5918};
5919
[email protected]631f1322010-04-30 17:59:115920TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:385921 HttpStreamFactory::set_use_alternate_protocols(true);
5922 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:115923
5924 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425925 proxy_config.set_auto_detect(true);
5926 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115927
[email protected]631f1322010-04-30 17:59:115928 CapturingProxyResolver* capturing_proxy_resolver =
5929 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385930 SessionDependencies session_deps(new ProxyService(
5931 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5932 NULL));
[email protected]631f1322010-04-30 17:59:115933
5934 HttpRequestInfo request;
5935 request.method = "GET";
5936 request.url = GURL("http://www.google.com/");
5937 request.load_flags = 0;
5938
5939 MockRead data_reads[] = {
5940 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355941 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:115942 MockRead("hello world"),
5943 MockRead(true, OK),
5944 };
5945
5946 StaticSocketDataProvider first_transaction(
5947 data_reads, arraysize(data_reads), NULL, 0);
5948 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5949
5950 SSLSocketDataProvider ssl(true, OK);
5951 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355952 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535953 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115954 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5955
[email protected]2bd93022010-07-17 00:58:445956 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:115957 MockWrite spdy_writes[] = {
5958 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5959 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425960 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135961 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115962 };
5963
[email protected]d911f1b2010-05-05 22:39:425964 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5965
[email protected]2bd93022010-07-17 00:58:445966 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5967 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:115968 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425969 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135970 CreateMockRead(*resp.get(), 4), // 2, 4
5971 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425972 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115973 };
5974
[email protected]d911f1b2010-05-05 22:39:425975 scoped_refptr<OrderedSocketData> spdy_data(
5976 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115977 spdy_reads, arraysize(spdy_reads),
5978 spdy_writes, arraysize(spdy_writes)));
5979 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5980
5981 TestCompletionCallback callback;
5982
5983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5984 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5985
5986 int rv = trans->Start(&request, &callback, BoundNetLog());
5987 EXPECT_EQ(ERR_IO_PENDING, rv);
5988 EXPECT_EQ(OK, callback.WaitForResult());
5989
5990 const HttpResponseInfo* response = trans->GetResponseInfo();
5991 ASSERT_TRUE(response != NULL);
5992 ASSERT_TRUE(response->headers != NULL);
5993 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535994 EXPECT_FALSE(response->was_fetched_via_spdy);
5995 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115996
5997 std::string response_data;
5998 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5999 EXPECT_EQ("hello world", response_data);
6000
6001 trans.reset(new HttpNetworkTransaction(session));
6002
6003 rv = trans->Start(&request, &callback, BoundNetLog());
6004 EXPECT_EQ(ERR_IO_PENDING, rv);
6005 EXPECT_EQ(OK, callback.WaitForResult());
6006
6007 response = trans->GetResponseInfo();
6008 ASSERT_TRUE(response != NULL);
6009 ASSERT_TRUE(response->headers != NULL);
6010 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536011 EXPECT_TRUE(response->was_fetched_via_spdy);
6012 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116013
6014 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6015 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426016 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6017 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116018 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426019 EXPECT_EQ("https://www.google.com/",
6020 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116021
[email protected]8e6441ca2010-08-19 05:56:386022 HttpStreamFactory::set_next_protos("");
6023 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116024}
[email protected]631f1322010-04-30 17:59:116025
[email protected]2ff8b312010-04-26 22:20:546026TEST_F(HttpNetworkTransactionTest,
6027 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386028 HttpStreamFactory::set_use_alternate_protocols(true);
6029 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546030 SessionDependencies session_deps;
6031
6032 HttpRequestInfo request;
6033 request.method = "GET";
6034 request.url = GURL("http://www.google.com/");
6035 request.load_flags = 0;
6036
6037 MockRead data_reads[] = {
6038 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356039 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546040 MockRead("hello world"),
6041 MockRead(true, OK),
6042 };
6043
6044 StaticSocketDataProvider first_transaction(
6045 data_reads, arraysize(data_reads), NULL, 0);
6046 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6047
6048 SSLSocketDataProvider ssl(true, OK);
6049 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356050 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536051 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546052 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536053 // Make sure we use ssl for spdy here.
6054 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546055
[email protected]2bd93022010-07-17 00:58:446056 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136057 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546058
[email protected]2bd93022010-07-17 00:58:446059 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6060 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546061 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136062 CreateMockRead(*resp),
6063 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546064 MockRead(true, 0, 0),
6065 };
6066
6067 scoped_refptr<DelayedSocketData> spdy_data(
6068 new DelayedSocketData(
6069 1, // wait for one write to finish before reading.
6070 spdy_reads, arraysize(spdy_reads),
6071 spdy_writes, arraysize(spdy_writes)));
6072 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6073
6074 TestCompletionCallback callback;
6075
6076 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6077
6078 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6079
[email protected]5a1d7ca2010-04-28 20:12:276080 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546081 EXPECT_EQ(ERR_IO_PENDING, rv);
6082 EXPECT_EQ(OK, callback.WaitForResult());
6083
6084 const HttpResponseInfo* response = trans->GetResponseInfo();
6085 ASSERT_TRUE(response != NULL);
6086 ASSERT_TRUE(response->headers != NULL);
6087 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6088
6089 std::string response_data;
6090 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6091 EXPECT_EQ("hello world", response_data);
6092
6093 // Set up an initial SpdySession in the pool to reuse.
[email protected]31e68d72010-08-25 06:36:586094 HostPortProxyPair pair(HostPortPair("www.google.com", 443),
6095 ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546096 scoped_refptr<SpdySession> spdy_session =
[email protected]b261d0e2010-08-02 19:13:246097 session->spdy_session_pool()->Get(pair, session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:216098 scoped_refptr<TCPSocketParams> tcp_params =
6099 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:366100 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:546101 trans.reset(new HttpNetworkTransaction(session));
6102
[email protected]5a1d7ca2010-04-28 20:12:276103 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546104 EXPECT_EQ(ERR_IO_PENDING, rv);
6105 EXPECT_EQ(OK, callback.WaitForResult());
6106
6107 response = trans->GetResponseInfo();
6108 ASSERT_TRUE(response != NULL);
6109 ASSERT_TRUE(response->headers != NULL);
6110 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536111 EXPECT_TRUE(response->was_fetched_via_spdy);
6112 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576113 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546114
6115 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6116 EXPECT_EQ("hello!", response_data);
6117
[email protected]8e6441ca2010-08-19 05:56:386118 HttpStreamFactory::set_next_protos("");
6119 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426120}
6121
[email protected]044de0642010-06-17 10:42:156122// GenerateAuthToken is a mighty big test.
6123// It tests all permutation of GenerateAuthToken behavior:
6124// - Synchronous and Asynchronous completion.
6125// - OK or error on completion.
6126// - Direct connection, non-authenticating proxy, and authenticating proxy.
6127// - HTTP or HTTPS backend (to include proxy tunneling).
6128// - Non-authenticating and authenticating backend.
6129//
6130// In all, there are 44 reasonable permuations (for example, if there are
6131// problems generating an auth token for an authenticating proxy, we don't
6132// need to test all permutations of the backend server).
6133//
6134// The test proceeds by going over each of the configuration cases, and
6135// potentially running up to three rounds in each of the tests. The TestConfig
6136// specifies both the configuration for the test as well as the expectations
6137// for the results.
6138TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
6139 const char* kServer = "http://www.example.com";
6140 const char* kSecureServer = "https://www.example.com";
6141 const char* kProxy = "myproxy:70";
6142 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6143
6144 enum AuthTiming {
6145 AUTH_NONE,
6146 AUTH_SYNC,
6147 AUTH_ASYNC,
6148 };
6149
6150 const MockWrite kGet(
6151 "GET / HTTP/1.1\r\n"
6152 "Host: www.example.com\r\n"
6153 "Connection: keep-alive\r\n\r\n");
6154 const MockWrite kGetProxy(
6155 "GET http://www.example.com/ HTTP/1.1\r\n"
6156 "Host: www.example.com\r\n"
6157 "Proxy-Connection: keep-alive\r\n\r\n");
6158 const MockWrite kGetAuth(
6159 "GET / HTTP/1.1\r\n"
6160 "Host: www.example.com\r\n"
6161 "Connection: keep-alive\r\n"
6162 "Authorization: auth_token\r\n\r\n");
6163 const MockWrite kGetProxyAuth(
6164 "GET http://www.example.com/ HTTP/1.1\r\n"
6165 "Host: www.example.com\r\n"
6166 "Proxy-Connection: keep-alive\r\n"
6167 "Proxy-Authorization: auth_token\r\n\r\n");
6168 const MockWrite kGetAuthThroughProxy(
6169 "GET http://www.example.com/ HTTP/1.1\r\n"
6170 "Host: www.example.com\r\n"
6171 "Proxy-Connection: keep-alive\r\n"
6172 "Authorization: auth_token\r\n\r\n");
6173 const MockWrite kGetAuthWithProxyAuth(
6174 "GET http://www.example.com/ HTTP/1.1\r\n"
6175 "Host: www.example.com\r\n"
6176 "Proxy-Connection: keep-alive\r\n"
6177 "Proxy-Authorization: auth_token\r\n"
6178 "Authorization: auth_token\r\n\r\n");
6179 const MockWrite kConnect(
6180 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6181 "Host: www.example.com\r\n"
6182 "Proxy-Connection: keep-alive\r\n\r\n");
6183 const MockWrite kConnectProxyAuth(
6184 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6185 "Host: www.example.com\r\n"
6186 "Proxy-Connection: keep-alive\r\n"
6187 "Proxy-Authorization: auth_token\r\n\r\n");
6188
6189 const MockRead kSuccess(
6190 "HTTP/1.1 200 OK\r\n"
6191 "Content-Type: text/html; charset=iso-8859-1\r\n"
6192 "Content-Length: 3\r\n\r\n"
6193 "Yes");
6194 const MockRead kFailure(
6195 "Should not be called.");
6196 const MockRead kServerChallenge(
6197 "HTTP/1.1 401 Unauthorized\r\n"
6198 "WWW-Authenticate: Mock realm=server\r\n"
6199 "Content-Type: text/html; charset=iso-8859-1\r\n"
6200 "Content-Length: 14\r\n\r\n"
6201 "Unauthorized\r\n");
6202 const MockRead kProxyChallenge(
6203 "HTTP/1.1 407 Unauthorized\r\n"
6204 "Proxy-Authenticate: Mock realm=proxy\r\n"
6205 "Proxy-Connection: close\r\n"
6206 "Content-Type: text/html; charset=iso-8859-1\r\n"
6207 "Content-Length: 14\r\n\r\n"
6208 "Unauthorized\r\n");
6209 const MockRead kProxyConnected(
6210 "HTTP/1.1 200 Connection Established\r\n\r\n");
6211
6212 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6213 // no constructors, but the C++ compiler on Windows warns about
6214 // unspecified data in compound literals. So, moved to using constructors,
6215 // and TestRound's created with the default constructor should not be used.
6216 struct TestRound {
6217 TestRound()
6218 : expected_rv(ERR_UNEXPECTED),
6219 extra_write(NULL),
6220 extra_read(NULL) {
6221 }
6222 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6223 int expected_rv_arg)
6224 : write(write_arg),
6225 read(read_arg),
6226 expected_rv(expected_rv_arg),
6227 extra_write(NULL),
6228 extra_read(NULL) {
6229 }
6230 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6231 int expected_rv_arg, const MockWrite* extra_write_arg,
6232 const MockWrite* extra_read_arg)
6233 : write(write_arg),
6234 read(read_arg),
6235 expected_rv(expected_rv_arg),
6236 extra_write(extra_write_arg),
6237 extra_read(extra_read_arg) {
6238 }
6239 MockWrite write;
6240 MockRead read;
6241 int expected_rv;
6242 const MockWrite* extra_write;
6243 const MockRead* extra_read;
6244 };
6245
6246 static const int kNoSSL = 500;
6247
6248 struct TestConfig {
6249 const char* proxy_url;
6250 AuthTiming proxy_auth_timing;
6251 int proxy_auth_rv;
6252 const char* server_url;
6253 AuthTiming server_auth_timing;
6254 int server_auth_rv;
6255 int num_auth_rounds;
6256 int first_ssl_round;
6257 TestRound rounds[3];
6258 } test_configs[] = {
6259 // Non-authenticating HTTP server with a direct connection.
6260 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6261 { TestRound(kGet, kSuccess, OK)}},
6262 // Authenticating HTTP server with a direct connection.
6263 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6264 { TestRound(kGet, kServerChallenge, OK),
6265 TestRound(kGetAuth, kSuccess, OK)}},
6266 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6267 { TestRound(kGet, kServerChallenge, OK),
6268 TestRound(kGetAuth, kFailure, kAuthErr)}},
6269 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6270 { TestRound(kGet, kServerChallenge, OK),
6271 TestRound(kGetAuth, kSuccess, OK)}},
6272 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6273 { TestRound(kGet, kServerChallenge, OK),
6274 TestRound(kGetAuth, kFailure, kAuthErr)}},
6275 // Non-authenticating HTTP server through a non-authenticating proxy.
6276 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6277 { TestRound(kGetProxy, kSuccess, OK)}},
6278 // Authenticating HTTP server through a non-authenticating proxy.
6279 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6280 { TestRound(kGetProxy, kServerChallenge, OK),
6281 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6282 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6283 { TestRound(kGetProxy, kServerChallenge, OK),
6284 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6285 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6286 { TestRound(kGetProxy, kServerChallenge, OK),
6287 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6288 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6289 { TestRound(kGetProxy, kServerChallenge, OK),
6290 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6291 // Non-authenticating HTTP server through an authenticating proxy.
6292 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6293 { TestRound(kGetProxy, kProxyChallenge, OK),
6294 TestRound(kGetProxyAuth, kSuccess, OK)}},
6295 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6296 { TestRound(kGetProxy, kProxyChallenge, OK),
6297 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6298 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6299 { TestRound(kGetProxy, kProxyChallenge, OK),
6300 TestRound(kGetProxyAuth, kSuccess, OK)}},
6301 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6302 { TestRound(kGetProxy, kProxyChallenge, OK),
6303 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6304 // Authenticating HTTP server through an authenticating proxy.
6305 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6306 { TestRound(kGetProxy, kProxyChallenge, OK),
6307 TestRound(kGetProxyAuth, kServerChallenge, OK),
6308 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6309 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6310 { TestRound(kGetProxy, kProxyChallenge, OK),
6311 TestRound(kGetProxyAuth, kServerChallenge, OK),
6312 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6313 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6314 { TestRound(kGetProxy, kProxyChallenge, OK),
6315 TestRound(kGetProxyAuth, kServerChallenge, OK),
6316 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6317 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6318 { TestRound(kGetProxy, kProxyChallenge, OK),
6319 TestRound(kGetProxyAuth, kServerChallenge, OK),
6320 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6321 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6322 { TestRound(kGetProxy, kProxyChallenge, OK),
6323 TestRound(kGetProxyAuth, kServerChallenge, OK),
6324 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6325 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6326 { TestRound(kGetProxy, kProxyChallenge, OK),
6327 TestRound(kGetProxyAuth, kServerChallenge, OK),
6328 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6329 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6330 { TestRound(kGetProxy, kProxyChallenge, OK),
6331 TestRound(kGetProxyAuth, kServerChallenge, OK),
6332 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6333 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6334 { TestRound(kGetProxy, kProxyChallenge, OK),
6335 TestRound(kGetProxyAuth, kServerChallenge, OK),
6336 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6337 // Non-authenticating HTTPS server with a direct connection.
6338 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6339 { TestRound(kGet, kSuccess, OK)}},
6340 // Authenticating HTTPS server with a direct connection.
6341 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6342 { TestRound(kGet, kServerChallenge, OK),
6343 TestRound(kGetAuth, kSuccess, OK)}},
6344 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6345 { TestRound(kGet, kServerChallenge, OK),
6346 TestRound(kGetAuth, kFailure, kAuthErr)}},
6347 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6348 { TestRound(kGet, kServerChallenge, OK),
6349 TestRound(kGetAuth, kSuccess, OK)}},
6350 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6351 { TestRound(kGet, kServerChallenge, OK),
6352 TestRound(kGetAuth, kFailure, kAuthErr)}},
6353 // Non-authenticating HTTPS server with a non-authenticating proxy.
6354 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6355 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6356 // Authenticating HTTPS server through a non-authenticating proxy.
6357 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6358 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6359 TestRound(kGetAuth, kSuccess, OK)}},
6360 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6361 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6362 TestRound(kGetAuth, kFailure, kAuthErr)}},
6363 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6364 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6365 TestRound(kGetAuth, kSuccess, OK)}},
6366 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6367 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6368 TestRound(kGetAuth, kFailure, kAuthErr)}},
6369 // Non-Authenticating HTTPS server through an authenticating proxy.
6370 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6371 { TestRound(kConnect, kProxyChallenge, OK),
6372 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6373 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6374 { TestRound(kConnect, kProxyChallenge, OK),
6375 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6376 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6377 { TestRound(kConnect, kProxyChallenge, OK),
6378 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6379 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6380 { TestRound(kConnect, kProxyChallenge, OK),
6381 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6382 // Authenticating HTTPS server through an authenticating proxy.
6383 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6384 { TestRound(kConnect, kProxyChallenge, OK),
6385 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6386 &kGet, &kServerChallenge),
6387 TestRound(kGetAuth, kSuccess, OK)}},
6388 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6389 { TestRound(kConnect, kProxyChallenge, OK),
6390 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6391 &kGet, &kServerChallenge),
6392 TestRound(kGetAuth, kFailure, kAuthErr)}},
6393 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6394 { TestRound(kConnect, kProxyChallenge, OK),
6395 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6396 &kGet, &kServerChallenge),
6397 TestRound(kGetAuth, kSuccess, OK)}},
6398 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6399 { TestRound(kConnect, kProxyChallenge, OK),
6400 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6401 &kGet, &kServerChallenge),
6402 TestRound(kGetAuth, kFailure, kAuthErr)}},
6403 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6404 { TestRound(kConnect, kProxyChallenge, OK),
6405 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6406 &kGet, &kServerChallenge),
6407 TestRound(kGetAuth, kSuccess, OK)}},
6408 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6409 { TestRound(kConnect, kProxyChallenge, OK),
6410 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6411 &kGet, &kServerChallenge),
6412 TestRound(kGetAuth, kFailure, kAuthErr)}},
6413 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6414 { TestRound(kConnect, kProxyChallenge, OK),
6415 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6416 &kGet, &kServerChallenge),
6417 TestRound(kGetAuth, kSuccess, OK)}},
6418 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6419 { TestRound(kConnect, kProxyChallenge, OK),
6420 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6421 &kGet, &kServerChallenge),
6422 TestRound(kGetAuth, kFailure, kAuthErr)}},
6423 };
6424
6425 SessionDependencies session_deps;
6426 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:006427 HttpAuthHandlerMock::Factory* auth_factory(
6428 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156429 session_deps.http_auth_handler_factory.reset(auth_factory);
6430
6431 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6432 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266433
6434 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156435 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006436 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156437 std::string auth_challenge = "Mock realm=proxy";
6438 GURL origin(test_config.proxy_url);
6439 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6440 auth_challenge.end());
6441 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6442 origin, BoundNetLog());
6443 auth_handler->SetGenerateExpectation(
6444 test_config.proxy_auth_timing == AUTH_ASYNC,
6445 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156446 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6447 }
6448 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006449 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156450 std::string auth_challenge = "Mock realm=server";
6451 GURL origin(test_config.server_url);
6452 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6453 auth_challenge.end());
6454 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6455 origin, BoundNetLog());
6456 auth_handler->SetGenerateExpectation(
6457 test_config.server_auth_timing == AUTH_ASYNC,
6458 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156459 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6460 }
6461 if (test_config.proxy_url) {
6462 session_deps.proxy_service =
6463 CreateFixedProxyService(test_config.proxy_url);
6464 } else {
6465 session_deps.proxy_service = ProxyService::CreateNull();
6466 }
6467
6468 HttpRequestInfo request;
6469 request.method = "GET";
6470 request.url = GURL(test_config.server_url);
6471 request.load_flags = 0;
6472
6473 scoped_ptr<HttpTransaction> trans(
6474 new HttpNetworkTransaction(CreateSession(&session_deps)));
6475
6476 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6477 const TestRound& read_write_round = test_config.rounds[round];
6478
6479 // Set up expected reads and writes.
6480 MockRead reads[2];
6481 reads[0] = read_write_round.read;
6482 size_t length_reads = 1;
6483 if (read_write_round.extra_read) {
6484 reads[1] = *read_write_round.extra_read;
6485 length_reads = 2;
6486 }
6487
6488 MockWrite writes[2];
6489 writes[0] = read_write_round.write;
6490 size_t length_writes = 1;
6491 if (read_write_round.extra_write) {
6492 writes[1] = *read_write_round.extra_write;
6493 length_writes = 2;
6494 }
6495 StaticSocketDataProvider data_provider(
6496 reads, length_reads, writes, length_writes);
6497 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6498
6499 // Add an SSL sequence if necessary.
6500 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6501 if (round >= test_config.first_ssl_round)
6502 session_deps.socket_factory.AddSSLSocketDataProvider(
6503 &ssl_socket_data_provider);
6504
6505 // Start or restart the transaction.
6506 TestCompletionCallback callback;
6507 int rv;
6508 if (round == 0) {
6509 rv = trans->Start(&request, &callback, BoundNetLog());
6510 } else {
[email protected]13c8a092010-07-29 06:15:446511 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156512 }
6513 if (rv == ERR_IO_PENDING)
6514 rv = callback.WaitForResult();
6515
6516 // Compare results with expected data.
6517 EXPECT_EQ(read_write_round.expected_rv, rv);
6518 const HttpResponseInfo* response = trans->GetResponseInfo();
6519 if (read_write_round.expected_rv == OK) {
6520 EXPECT_FALSE(response == NULL);
6521 } else {
6522 EXPECT_TRUE(response == NULL);
6523 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6524 continue;
6525 }
6526 if (round + 1 < test_config.num_auth_rounds) {
6527 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6528 } else {
6529 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6530 }
6531 }
[email protected]e5ae96a2010-04-14 20:12:456532 }
[email protected]e60e47a2010-07-14 03:37:186533
6534 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
6535 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:456536}
6537
[email protected]c871bce92010-07-15 21:51:146538TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6539 // Do multi-round authentication and make sure it works correctly.
6540 SessionDependencies session_deps;
6541 HttpAuthHandlerMock::Factory* auth_factory(
6542 new HttpAuthHandlerMock::Factory());
6543 session_deps.http_auth_handler_factory.reset(auth_factory);
6544 session_deps.proxy_service = ProxyService::CreateNull();
6545 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6546 session_deps.host_resolver->set_synchronous_mode(true);
6547
6548 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6549 auth_handler->set_connection_based(true);
6550 std::string auth_challenge = "Mock realm=server";
6551 GURL origin("http://www.example.com");
6552 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6553 auth_challenge.end());
6554 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6555 origin, BoundNetLog());
6556 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6557
6558 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6559 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6560
6561 int rv = OK;
6562 const HttpResponseInfo* response = NULL;
6563 HttpRequestInfo request;
6564 request.method = "GET";
6565 request.url = origin;
6566 request.load_flags = 0;
6567 TestCompletionCallback callback;
6568
6569 const MockWrite kGet(
6570 "GET / HTTP/1.1\r\n"
6571 "Host: www.example.com\r\n"
6572 "Connection: keep-alive\r\n\r\n");
6573 const MockWrite kGetAuth(
6574 "GET / HTTP/1.1\r\n"
6575 "Host: www.example.com\r\n"
6576 "Connection: keep-alive\r\n"
6577 "Authorization: auth_token\r\n\r\n");
6578
6579 const MockRead kServerChallenge(
6580 "HTTP/1.1 401 Unauthorized\r\n"
6581 "WWW-Authenticate: Mock realm=server\r\n"
6582 "Content-Type: text/html; charset=iso-8859-1\r\n"
6583 "Content-Length: 14\r\n\r\n"
6584 "Unauthorized\r\n");
6585 const MockRead kSuccess(
6586 "HTTP/1.1 200 OK\r\n"
6587 "Content-Type: text/html; charset=iso-8859-1\r\n"
6588 "Content-Length: 3\r\n\r\n"
6589 "Yes");
6590
6591 MockWrite writes[] = {
6592 // First round
6593 kGet,
6594 // Second round
6595 kGetAuth,
6596 // Third round
6597 kGetAuth,
6598 };
6599 MockRead reads[] = {
6600 // First round
6601 kServerChallenge,
6602 // Second round
6603 kServerChallenge,
6604 // Third round
6605 kSuccess,
6606 };
6607 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6608 writes, arraysize(writes));
6609 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6610
6611 // First round
6612 auth_handler->SetGenerateExpectation(false, OK);
6613 rv = trans->Start(&request, &callback, BoundNetLog());
6614 if (rv == ERR_IO_PENDING)
6615 rv = callback.WaitForResult();
6616 EXPECT_EQ(OK, rv);
6617 response = trans->GetResponseInfo();
6618 ASSERT_FALSE(response == NULL);
6619 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6620
6621 // Second round
6622 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446623 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146624 if (rv == ERR_IO_PENDING)
6625 rv = callback.WaitForResult();
6626 EXPECT_EQ(OK, rv);
6627 response = trans->GetResponseInfo();
6628 ASSERT_FALSE(response == NULL);
6629 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6630
6631 // Third round
6632 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446633 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146634 if (rv == ERR_IO_PENDING)
6635 rv = callback.WaitForResult();
6636 EXPECT_EQ(OK, rv);
6637 response = trans->GetResponseInfo();
6638 ASSERT_FALSE(response == NULL);
6639 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6640}
6641
[email protected]aeaca1f2010-04-20 22:05:216642class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6643 public:
[email protected]06650c52010-06-03 00:49:176644 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216645 : fail_all_(fail_all) {
6646 }
6647
6648 virtual MockRead GetNextRead() {
6649 if (fail_all_)
6650 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6651
6652 return MockRead(false /* async */,
6653 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6654 }
6655
6656 virtual MockWriteResult OnWrite(const std::string& data) {
6657 return MockWriteResult(false /* async */, data.size());
6658 }
6659
6660 void Reset() {
6661 }
6662
6663 private:
6664 const bool fail_all_;
6665};
6666
6667// Test that we restart a connection when we see a decompression failure from
6668// the peer during the handshake. (In the real world we'll restart with SSLv3
6669// and we won't offer DEFLATE in that case.)
6670TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6671 HttpRequestInfo request;
6672 request.method = "GET";
6673 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6674 request.load_flags = 0;
6675
6676 SessionDependencies session_deps;
6677 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6678 false /* fail all reads */);
6679 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6680 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116681 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216682 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6683 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6684 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6685 session_deps.socket_factory.AddSSLSocketDataProvider(
6686 &ssl_socket_data_provider1);
6687 session_deps.socket_factory.AddSSLSocketDataProvider(
6688 &ssl_socket_data_provider2);
6689
[email protected]e60e47a2010-07-14 03:37:186690 // Work around http://crbug.com/37454
6691 StaticSocketDataProvider bug37454_connection;
6692 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6693 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6694
[email protected]aeaca1f2010-04-20 22:05:216695 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6696 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6697 TestCompletionCallback callback;
6698
[email protected]5a1d7ca2010-04-28 20:12:276699 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216700 EXPECT_EQ(ERR_IO_PENDING, rv);
6701 EXPECT_EQ(OK, callback.WaitForResult());
6702
6703 const HttpResponseInfo* response = trans->GetResponseInfo();
6704 ASSERT_TRUE(response != NULL);
6705 ASSERT_TRUE(response->headers != NULL);
6706 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6707
6708 std::string response_data;
6709 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6710 EXPECT_EQ("ok.", response_data);
6711}
6712
6713// Test that we restart a connection if we get a decompression failure from the
6714// peer while reading the first bytes from the connection. This occurs when the
6715// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6716// in the handshake.
6717TEST_F(HttpNetworkTransactionTest,
6718 RestartAfterTLSDecompressionFailureWithFalseStart) {
6719 HttpRequestInfo request;
6720 request.method = "GET";
6721 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6722 request.load_flags = 0;
6723
6724 SessionDependencies session_deps;
6725 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6726 true /* fail all reads */);
6727 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6728 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6729 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6730 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6731 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6732 session_deps.socket_factory.AddSSLSocketDataProvider(
6733 &ssl_socket_data_provider1);
6734 session_deps.socket_factory.AddSSLSocketDataProvider(
6735 &ssl_socket_data_provider2);
6736
6737 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6738 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6739 TestCompletionCallback callback;
6740
[email protected]5a1d7ca2010-04-28 20:12:276741 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216742 EXPECT_EQ(ERR_IO_PENDING, rv);
6743 EXPECT_EQ(OK, callback.WaitForResult());
6744
6745 const HttpResponseInfo* response = trans->GetResponseInfo();
6746 ASSERT_TRUE(response != NULL);
6747 ASSERT_TRUE(response->headers != NULL);
6748 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6749
6750 std::string response_data;
6751 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6752 EXPECT_EQ("ok.", response_data);
6753}
6754
[email protected]65041fa2010-05-21 06:56:536755// This tests the case that a request is issued via http instead of spdy after
6756// npn is negotiated.
6757TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:386758 HttpStreamFactory::set_use_alternate_protocols(true);
6759 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:536760 SessionDependencies session_deps;
6761 HttpRequestInfo request;
6762 request.method = "GET";
6763 request.url = GURL("https://www.google.com/");
6764 request.load_flags = 0;
6765
6766 MockWrite data_writes[] = {
6767 MockWrite("GET / HTTP/1.1\r\n"
6768 "Host: www.google.com\r\n"
6769 "Connection: keep-alive\r\n\r\n"),
6770 };
6771
6772 MockRead data_reads[] = {
6773 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356774 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536775 MockRead("hello world"),
6776 MockRead(false, OK),
6777 };
6778
6779 SSLSocketDataProvider ssl(true, OK);
6780 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6781 ssl.next_proto = "http/1.1";
6782
6783 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6784
6785 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6786 data_writes, arraysize(data_writes));
6787 session_deps.socket_factory.AddSocketDataProvider(&data);
6788
6789 TestCompletionCallback callback;
6790
6791 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6792 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6793
6794 int rv = trans->Start(&request, &callback, BoundNetLog());
6795
6796 EXPECT_EQ(ERR_IO_PENDING, rv);
6797 EXPECT_EQ(OK, callback.WaitForResult());
6798
6799 const HttpResponseInfo* response = trans->GetResponseInfo();
6800 ASSERT_TRUE(response != NULL);
6801 ASSERT_TRUE(response->headers != NULL);
6802 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6803
6804 std::string response_data;
6805 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6806 EXPECT_EQ("hello world", response_data);
6807
6808 EXPECT_FALSE(response->was_fetched_via_spdy);
6809 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576810 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536811
[email protected]8e6441ca2010-08-19 05:56:386812 HttpStreamFactory::set_next_protos("");
6813 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:536814}
[email protected]26ef6582010-06-24 02:30:476815
6816TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6817 // Simulate the SSL handshake completing with an NPN negotiation
6818 // followed by an immediate server closing of the socket.
6819 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:386820 HttpStreamFactory::set_use_alternate_protocols(true);
6821 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476822 SessionDependencies session_deps;
6823
6824 HttpRequestInfo request;
6825 request.method = "GET";
6826 request.url = GURL("https://www.google.com/");
6827 request.load_flags = 0;
6828
6829 SSLSocketDataProvider ssl(true, OK);
6830 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356831 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476832 ssl.was_npn_negotiated = true;
6833 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6834
[email protected]2bd93022010-07-17 00:58:446835 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136836 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476837
6838 MockRead spdy_reads[] = {
6839 MockRead(false, 0, 0) // Not async - return 0 immediately.
6840 };
6841
6842 scoped_refptr<DelayedSocketData> spdy_data(
6843 new DelayedSocketData(
6844 0, // don't wait in this case, immediate hangup.
6845 spdy_reads, arraysize(spdy_reads),
6846 spdy_writes, arraysize(spdy_writes)));
6847 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6848
6849 TestCompletionCallback callback;
6850
6851 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6852 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6853
6854 int rv = trans->Start(&request, &callback, BoundNetLog());
6855 EXPECT_EQ(ERR_IO_PENDING, rv);
6856 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6857
[email protected]8e6441ca2010-08-19 05:56:386858 HttpStreamFactory::set_next_protos("");
6859 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:476860}
[email protected]65d34382010-07-01 18:12:266861
[email protected]f45c1ee2010-08-03 00:54:306862TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
6863 // This test ensures that the URL passed into the proxy is upgraded
6864 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:386865 HttpStreamFactory::set_use_alternate_protocols(true);
6866 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:306867 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
6868
6869 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6870 HttpAuthHandlerMock::Factory* auth_factory =
6871 new HttpAuthHandlerMock::Factory();
6872 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
6873 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6874 auth_factory->set_do_init_from_challenge(true);
6875 session_deps.http_auth_handler_factory.reset(auth_factory);
6876
6877 HttpRequestInfo request;
6878 request.method = "GET";
6879 request.url = GURL("http://www.google.com");
6880 request.load_flags = 0;
6881
6882 // First round goes unauthenticated through the proxy.
6883 MockWrite data_writes_1[] = {
6884 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6885 "Host: www.google.com\r\n"
6886 "Proxy-Connection: keep-alive\r\n"
6887 "\r\n"),
6888 };
6889 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:596890 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:306891 MockRead("HTTP/1.1 200 OK\r\n"
6892 "Alternate-Protocol: 443:npn-spdy/2\r\n"
6893 "Proxy-Connection: close\r\n"
6894 "\r\n"),
6895 };
6896 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
6897 data_writes_1, arraysize(data_writes_1));
6898
6899 // Second round tries to tunnel to www.google.com due to the
6900 // Alternate-Protocol announcement in the first round. It fails due
6901 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:596902 // After the failure, a tunnel is established to www.google.com using
6903 // Proxy-Authorization headers. There is then a SPDY request round.
6904 //
6905 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
6906 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
6907 // does a Disconnect and Connect on the same socket, rather than trying
6908 // to obtain a new one.
6909 //
6910 // NOTE: Originally, the proxy response to the second CONNECT request
6911 // simply returned another 407 so the unit test could skip the SSL connection
6912 // establishment and SPDY framing issues. Alas, the
6913 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:306914 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:596915
[email protected]f45c1ee2010-08-03 00:54:306916 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6917 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6918 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6919
[email protected]394816e92010-08-03 07:38:596920 MockWrite data_writes_2[] = {
6921 // First connection attempt without Proxy-Authorization.
6922 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6923 "Host: www.google.com\r\n"
6924 "Proxy-Connection: keep-alive\r\n"
6925 "\r\n"),
6926
6927 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:306928 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6929 "Host: www.google.com\r\n"
6930 "Proxy-Connection: keep-alive\r\n"
6931 "Proxy-Authorization: auth_token\r\n"
6932 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:306933
[email protected]394816e92010-08-03 07:38:596934 // SPDY request
6935 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:306936 };
[email protected]394816e92010-08-03 07:38:596937 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
6938 "Proxy-Authenticate: Mock\r\n"
6939 "Proxy-Connection: close\r\n"
6940 "\r\n");
6941 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6942 MockRead data_reads_2[] = {
6943 // First connection attempt fails
6944 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
6945 MockRead(true, kRejectConnectResponse,
6946 arraysize(kRejectConnectResponse) - 1, 1),
6947
6948 // Second connection attempt passes
6949 MockRead(true, kAcceptConnectResponse,
6950 arraysize(kAcceptConnectResponse) -1, 4),
6951
6952 // SPDY response
6953 CreateMockRead(*resp.get(), 6),
6954 CreateMockRead(*data.get(), 6),
6955 MockRead(true, 0, 0, 6),
6956 };
6957 scoped_refptr<OrderedSocketData> data_2(
6958 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
6959 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:306960
6961 SSLSocketDataProvider ssl(true, OK);
6962 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6963 ssl.next_proto = "spdy/2";
6964 ssl.was_npn_negotiated = true;
6965
6966 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:596967 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:306968 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6969 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6970
6971 // First round should work and provide the Alternate-Protocol state.
6972 TestCompletionCallback callback_1;
6973 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
6974 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
6975 EXPECT_EQ(ERR_IO_PENDING, rv);
6976 EXPECT_EQ(OK, callback_1.WaitForResult());
6977
6978 // Second round should attempt a tunnel connect and get an auth challenge.
6979 TestCompletionCallback callback_2;
6980 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
6981 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
6982 EXPECT_EQ(ERR_IO_PENDING, rv);
6983 EXPECT_EQ(OK, callback_2.WaitForResult());
6984 const HttpResponseInfo* response = trans_2->GetResponseInfo();
6985 ASSERT_FALSE(response == NULL);
6986 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6987
6988 // Restart with auth. Tunnel should work and response received.
6989 TestCompletionCallback callback_3;
6990 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
6991 EXPECT_EQ(ERR_IO_PENDING, rv);
6992 EXPECT_EQ(OK, callback_3.WaitForResult());
6993
6994 // After all that work, these two lines (or actually, just the scheme) are
6995 // what this test is all about. Make sure it happens correctly.
6996 const GURL& request_url = auth_handler->request_url();
6997 EXPECT_EQ("https", request_url.scheme());
6998 EXPECT_EQ("www.google.com", request_url.host());
6999
[email protected]8e6441ca2010-08-19 05:56:387000 HttpStreamFactory::set_next_protos("");
7001 HttpStreamFactory::set_use_alternate_protocols(false);
7002}
7003
7004// Test that if we cancel the transaction as the connection is completing, that
7005// everything tears down correctly.
7006TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7007 // Setup everything about the connection to complete synchronously, so that
7008 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7009 // for is the callback from the HttpStreamRequest.
7010 // Then cancel the transaction.
7011 // Verify that we don't crash.
7012 MockConnect mock_connect(false, OK);
7013 MockRead data_reads[] = {
7014 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7015 MockRead(false, "hello world"),
7016 MockRead(false, OK),
7017 };
7018
7019 SessionDependencies session_deps;
7020 session_deps.host_resolver->set_synchronous_mode(true);
7021 scoped_ptr<HttpTransaction> trans(
7022 new HttpNetworkTransaction(CreateSession(&session_deps)));
7023
7024 HttpRequestInfo request;
7025 request.method = "GET";
7026 request.url = GURL("http://www.google.com/");
7027 request.load_flags = 0;
7028
7029 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7030 data.set_connect_data(mock_connect);
7031 session_deps.socket_factory.AddSocketDataProvider(&data);
7032
7033 TestCompletionCallback callback;
7034
7035 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7036 int rv = trans->Start(&request, &callback, log.bound());
7037 EXPECT_EQ(ERR_IO_PENDING, rv);
7038 trans.reset(); // Cancel the transaction here.
7039
7040 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307041}
7042
[email protected]76a505b2010-08-25 06:23:007043// Test a basic GET request through a proxy.
7044TEST_F(HttpNetworkTransactionTest, ProxyGet) {
7045 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7046 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7047 session_deps.net_log = log.bound().net_log();
7048 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7049
7050 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7051
7052 HttpRequestInfo request;
7053 request.method = "GET";
7054 request.url = GURL("http://www.google.com/");
7055
7056 MockWrite data_writes1[] = {
7057 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7058 "Host: www.google.com\r\n"
7059 "Proxy-Connection: keep-alive\r\n\r\n"),
7060 };
7061
7062 MockRead data_reads1[] = {
7063 MockRead("HTTP/1.1 200 OK\r\n"),
7064 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7065 MockRead("Content-Length: 100\r\n\r\n"),
7066 MockRead(false, OK),
7067 };
7068
7069 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7070 data_writes1, arraysize(data_writes1));
7071 session_deps.socket_factory.AddSocketDataProvider(&data1);
7072
7073 TestCompletionCallback callback1;
7074
7075 int rv = trans->Start(&request, &callback1, log.bound());
7076 EXPECT_EQ(ERR_IO_PENDING, rv);
7077
7078 rv = callback1.WaitForResult();
7079 EXPECT_EQ(OK, rv);
7080
7081 const HttpResponseInfo* response = trans->GetResponseInfo();
7082 ASSERT_FALSE(response == NULL);
7083
7084 EXPECT_TRUE(response->headers->IsKeepAlive());
7085 EXPECT_EQ(200, response->headers->response_code());
7086 EXPECT_EQ(100, response->headers->GetContentLength());
7087 EXPECT_TRUE(response->was_fetched_via_proxy);
7088 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7089}
7090
7091// Test a basic HTTPS GET request through a proxy.
7092TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
7093 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7094 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7095 session_deps.net_log = log.bound().net_log();
7096 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7097
7098 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7099
7100 HttpRequestInfo request;
7101 request.method = "GET";
7102 request.url = GURL("https://www.google.com/");
7103
7104 // Since we have proxy, should try to establish tunnel.
7105 MockWrite data_writes1[] = {
7106 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7107 "Host: www.google.com\r\n"
7108 "Proxy-Connection: keep-alive\r\n\r\n"),
7109
7110 MockWrite("GET / HTTP/1.1\r\n"
7111 "Host: www.google.com\r\n"
7112 "Connection: keep-alive\r\n\r\n"),
7113 };
7114
7115 MockRead data_reads1[] = {
7116 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7117
7118 MockRead("HTTP/1.1 200 OK\r\n"),
7119 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7120 MockRead("Content-Length: 100\r\n\r\n"),
7121 MockRead(false, OK),
7122 };
7123
7124 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7125 data_writes1, arraysize(data_writes1));
7126 session_deps.socket_factory.AddSocketDataProvider(&data1);
7127 SSLSocketDataProvider ssl(true, OK);
7128 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7129
7130 TestCompletionCallback callback1;
7131
7132 int rv = trans->Start(&request, &callback1, log.bound());
7133 EXPECT_EQ(ERR_IO_PENDING, rv);
7134
7135 rv = callback1.WaitForResult();
7136 EXPECT_EQ(OK, rv);
7137 size_t pos = ExpectLogContainsSomewhere(
7138 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7139 NetLog::PHASE_NONE);
7140 ExpectLogContainsSomewhere(
7141 log.entries(), pos,
7142 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7143 NetLog::PHASE_NONE);
7144
7145 const HttpResponseInfo* response = trans->GetResponseInfo();
7146 ASSERT_FALSE(response == NULL);
7147
7148 EXPECT_TRUE(response->headers->IsKeepAlive());
7149 EXPECT_EQ(200, response->headers->response_code());
7150 EXPECT_EQ(100, response->headers->GetContentLength());
7151 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7152 EXPECT_TRUE(response->was_fetched_via_proxy);
7153}
7154
7155// Test a basic HTTPS GET request through a proxy, but the server hangs up
7156// while establishing the tunnel.
7157TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
7158 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7159 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7160 session_deps.net_log = log.bound().net_log();
7161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7162
7163 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7164
7165 HttpRequestInfo request;
7166 request.method = "GET";
7167 request.url = GURL("https://www.google.com/");
7168
7169 // Since we have proxy, should try to establish tunnel.
7170 MockWrite data_writes1[] = {
7171 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7172 "Host: www.google.com\r\n"
7173 "Proxy-Connection: keep-alive\r\n\r\n"),
7174
7175 MockWrite("GET / HTTP/1.1\r\n"
7176 "Host: www.google.com\r\n"
7177 "Connection: keep-alive\r\n\r\n"),
7178 };
7179
7180 MockRead data_reads1[] = {
7181 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7182 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7183 MockRead(true, 0, 0), // EOF
7184 };
7185
7186 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7187 data_writes1, arraysize(data_writes1));
7188 session_deps.socket_factory.AddSocketDataProvider(&data1);
7189 SSLSocketDataProvider ssl(true, OK);
7190 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7191
7192 TestCompletionCallback callback1;
7193
7194 int rv = trans->Start(&request, &callback1, log.bound());
7195 EXPECT_EQ(ERR_IO_PENDING, rv);
7196
7197 rv = callback1.WaitForResult();
7198 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7199 size_t pos = ExpectLogContainsSomewhere(
7200 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7201 NetLog::PHASE_NONE);
7202 ExpectLogContainsSomewhere(
7203 log.entries(), pos,
7204 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7205 NetLog::PHASE_NONE);
7206}
7207
[email protected]89ceba9a2009-03-21 03:46:067208} // namespace net