blob: b5919e62050258b88bd69da7120686c7ca076e0b [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]169d0012010-05-10 23:20:1216#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3317#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3218#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1219#include "net/base/net_log.h"
20#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3121#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4222#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3323#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5224#include "net/base/test_completion_callback.h"
25#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1226#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0027#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2928#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5729#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5731#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5232#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5333#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1134#include "net/proxy/proxy_resolver.h"
35#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4436#include "net/socket/client_socket_factory.h"
37#include "net/socket/socket_test_util.h"
38#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5439#include "net/spdy/spdy_framer.h"
40#include "net/spdy/spdy_session.h"
41#include "net/spdy/spdy_session_pool.h"
42#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5243#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1544#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5245
46//-----------------------------------------------------------------------------
47
[email protected]13c8a092010-07-29 06:15:4448namespace {
49
50const string16 kBar(ASCIIToUTF16("bar"));
51const string16 kBar2(ASCIIToUTF16("bar2"));
52const string16 kBar3(ASCIIToUTF16("bar3"));
53const string16 kBaz(ASCIIToUTF16("baz"));
54const string16 kFirst(ASCIIToUTF16("first"));
55const string16 kFoo(ASCIIToUTF16("foo"));
56const string16 kFoo2(ASCIIToUTF16("foo2"));
57const string16 kFoo3(ASCIIToUTF16("foo3"));
58const string16 kFou(ASCIIToUTF16("fou"));
59const string16 kSecond(ASCIIToUTF16("second"));
60const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
61const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
62
63} // namespace
64
[email protected]89ceba9a2009-03-21 03:46:0665namespace net {
66
[email protected]2d731a32010-04-29 01:04:0667class HttpNetworkSessionPeer {
68 public:
69 explicit HttpNetworkSessionPeer(
70 const scoped_refptr<HttpNetworkSession>& session)
71 : session_(session) {}
72
73 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
74 session_->tcp_socket_pool_ = pool;
75 }
76
77 void SetSocketPoolForSOCKSProxy(
78 const HostPortPair& socks_proxy,
79 const scoped_refptr<SOCKSClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1880 session_->socks_socket_pools_[socks_proxy] = pool;
[email protected]2d731a32010-04-29 01:04:0681 }
82
83 void SetSocketPoolForHTTPProxy(
84 const HostPortPair& http_proxy,
[email protected]e772db3f2010-07-12 18:11:1385 const scoped_refptr<HttpProxyClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1886 session_->http_proxy_socket_pools_[http_proxy] = pool;
87 }
88
89 void SetSSLSocketPool(const scoped_refptr<SSLClientSocketPool>& pool) {
90 session_->ssl_socket_pool_ = pool;
91 }
92
93 void SetSocketPoolForSSLWithProxy(
94 const HostPortPair& proxy_host,
95 const scoped_refptr<SSLClientSocketPool>& pool) {
96 session_->ssl_socket_pools_for_proxies_[proxy_host] = pool;
[email protected]2d731a32010-04-29 01:04:0697 }
98
99 private:
100 const scoped_refptr<HttpNetworkSession> session_;
101
102 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
103};
104
[email protected]e44de5d2009-06-05 20:12:45105// Helper to manage the lifetimes of the dependencies for a
106// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44107struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59108 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42109 SessionDependencies()
110 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:37111 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:10112 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52113 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54114 spdy_session_pool(new SpdySessionPool()),
115 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59116
117 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45118 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42119 : host_resolver(new MockHostResolver),
120 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10121 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52122 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54123 spdy_session_pool(new SpdySessionPool()),
124 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59125
[email protected]a2c2fb92009-07-18 07:31:04126 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:09127 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42128 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59129 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50130 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52131 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]a7ea8832010-07-12 17:54:54132 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59133};
134
[email protected]1c773ea12009-04-28 19:58:42135ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50136 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48137 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39138 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53139}
140
[email protected]228ff742009-06-05 01:19:59141HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38142 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09143 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42144 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10145 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52146 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17147 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44148 NULL,
[email protected]a7ea8832010-07-12 17:54:54149 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14150}
151
[email protected]89836e22008-09-25 20:33:42152class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52153 public:
[email protected]2ff8b312010-04-26 22:20:54154 virtual void SetUp() {
155 spdy::SpdyFramer::set_enable_compression_default(false);
156 }
157
[email protected]0e75a732008-10-16 20:36:09158 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54159 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09160 // Empty the current queue.
161 MessageLoop::current()->RunAllPending();
162 PlatformTest::TearDown();
163 }
164
[email protected]3d2a59b2008-09-26 19:44:25165 protected:
166 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52167
[email protected]ff007e162009-05-23 09:13:15168 struct SimpleGetHelperResult {
169 int rv;
170 std::string status_line;
171 std::string response_data;
172 };
initial.commit586acc5fe2008-07-26 22:42:52173
[email protected]31a2bfe2010-02-09 08:03:39174 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
175 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15176 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52177
[email protected]228ff742009-06-05 01:19:59178 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40179 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43180 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52181
[email protected]ff007e162009-05-23 09:13:15182 HttpRequestInfo request;
183 request.method = "GET";
184 request.url = GURL("http://www.google.com/");
185 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52186
[email protected]31a2bfe2010-02-09 08:03:39187 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59188 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52189
[email protected]ff007e162009-05-23 09:13:15190 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52191
[email protected]169d0012010-05-10 23:20:12192 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
193 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15194 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52195
[email protected]ff007e162009-05-23 09:13:15196 out.rv = callback.WaitForResult();
197 if (out.rv != OK)
198 return out;
199
200 const HttpResponseInfo* response = trans->GetResponseInfo();
201 EXPECT_TRUE(response != NULL);
202
203 EXPECT_TRUE(response->headers != NULL);
204 out.status_line = response->headers->GetStatusLine();
205
206 rv = ReadTransaction(trans.get(), &out.response_data);
207 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39208 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12209 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
210 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39211 ExpectLogContainsSomewhere(
212 log.entries(), pos,
213 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
214 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15215
[email protected]aecfbf22008-10-16 02:02:47216 return out;
[email protected]ff007e162009-05-23 09:13:15217 }
initial.commit586acc5fe2008-07-26 22:42:52218
[email protected]ff007e162009-05-23 09:13:15219 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
220 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52221
[email protected]ff007e162009-05-23 09:13:15222 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15223};
[email protected]231d5a32008-09-13 00:45:27224
[email protected]15a5ccf82008-10-23 19:57:43225// Fill |str| with a long header list that consumes >= |size| bytes.
226void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19227 const char* row =
228 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
229 const int sizeof_row = strlen(row);
230 const int num_rows = static_cast<int>(
231 ceil(static_cast<float>(size) / sizeof_row));
232 const int sizeof_data = num_rows * sizeof_row;
233 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43234 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51235
[email protected]4ddaf2502008-10-23 18:26:19236 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43237 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19238}
239
[email protected]385a4672009-03-11 22:21:29240// Alternative functions that eliminate randomness and dependency on the local
241// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20242void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29243 static const uint8 bytes[] = {
244 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
245 };
246 static size_t current_byte = 0;
247 for (size_t i = 0; i < n; ++i) {
248 output[i] = bytes[current_byte++];
249 current_byte %= arraysize(bytes);
250 }
251}
252
[email protected]fe2bc6a2009-03-23 16:52:20253void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29254 static const uint8 bytes[] = {
255 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
256 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
257 };
258 static size_t current_byte = 0;
259 for (size_t i = 0; i < n; ++i) {
260 output[i] = bytes[current_byte++];
261 current_byte %= arraysize(bytes);
262 }
263}
264
[email protected]fe2bc6a2009-03-23 16:52:20265std::string MockGetHostName() {
266 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29267}
268
[email protected]e60e47a2010-07-14 03:37:18269template<typename ParentPool>
270class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31271 public:
[email protected]e60e47a2010-07-14 03:37:18272 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
273
[email protected]d80a4322009-08-14 07:07:49274 const std::string last_group_name_received() const {
275 return last_group_name_;
276 }
277
[email protected]684970b2009-08-14 04:54:46278 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49279 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31280 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31281 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46282 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53283 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31284 last_group_name_ = group_name;
285 return ERR_IO_PENDING;
286 }
[email protected]04e5be32009-06-26 20:00:31287 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21288 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31289 virtual void ReleaseSocket(const std::string& group_name,
290 ClientSocket* socket) {}
291 virtual void CloseIdleSockets() {}
292 virtual HostResolver* GetHostResolver() const {
293 return NULL;
294 }
295 virtual int IdleSocketCount() const {
296 return 0;
297 }
298 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
299 return 0;
300 }
301 virtual LoadState GetLoadState(const std::string& group_name,
302 const ClientSocketHandle* handle) const {
303 return LOAD_STATE_IDLE;
304 }
[email protected]a796bcec2010-03-22 17:17:26305 virtual base::TimeDelta ConnectionTimeout() const {
306 return base::TimeDelta();
307 }
[email protected]d80a4322009-08-14 07:07:49308
309 private:
[email protected]04e5be32009-06-26 20:00:31310 std::string last_group_name_;
311};
312
[email protected]2d731a32010-04-29 01:04:06313typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11314CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13315typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
316CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06317typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11318CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18319typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
320CaptureGroupNameSSLSocketPool;
321
322template<typename ParentPool>
323CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
324 HttpNetworkSession* session)
325 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
326
327template<>
328CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
329 HttpNetworkSession* session)
330 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
331 NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11332
[email protected]231d5a32008-09-13 00:45:27333//-----------------------------------------------------------------------------
334
[email protected]dae22c52010-07-30 02:16:35335// This is the expected list of advertised protocols from the browser's NPN
336// list.
337static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
338
339// This is the expected return from a current server advertising SPDY.
340static const char kAlternateProtocolHttpHeader[] =
341 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
342
[email protected]231d5a32008-09-13 00:45:27343TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59344 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40345 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43346 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27347}
348
349TEST_F(HttpNetworkTransactionTest, SimpleGET) {
350 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35351 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
352 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42353 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27354 };
[email protected]31a2bfe2010-02-09 08:03:39355 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
356 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42357 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27358 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
359 EXPECT_EQ("hello world", out.response_data);
360}
361
362// Response with no status line.
363TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
364 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35365 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42366 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27367 };
[email protected]31a2bfe2010-02-09 08:03:39368 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
369 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42370 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27371 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
372 EXPECT_EQ("hello world", out.response_data);
373}
374
375// Allow up to 4 bytes of junk to precede status line.
376TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
377 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35378 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42379 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27380 };
[email protected]31a2bfe2010-02-09 08:03:39381 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
382 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42383 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27384 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
385 EXPECT_EQ("DATA", out.response_data);
386}
387
388// Allow up to 4 bytes of junk to precede status line.
389TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
390 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35391 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42392 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27393 };
[email protected]31a2bfe2010-02-09 08:03:39394 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
395 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42396 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27397 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
398 EXPECT_EQ("DATA", out.response_data);
399}
400
401// Beyond 4 bytes of slop and it should fail to find a status line.
402TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
403 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35404 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42405 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27406 };
[email protected]31a2bfe2010-02-09 08:03:39407 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
408 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42409 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25410 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
411 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27412}
413
414// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
415TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
416 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35417 MockRead("\n"),
418 MockRead("\n"),
419 MockRead("Q"),
420 MockRead("J"),
421 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42422 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27423 };
[email protected]31a2bfe2010-02-09 08:03:39424 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
425 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42426 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27427 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
428 EXPECT_EQ("DATA", out.response_data);
429}
430
431// Close the connection before enough bytes to have a status line.
432TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
433 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35434 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42435 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27436 };
[email protected]31a2bfe2010-02-09 08:03:39437 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
438 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42439 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27440 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
441 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52442}
443
[email protected]f9d44aa2008-09-23 23:57:17444// Simulate a 204 response, lacking a Content-Length header, sent over a
445// persistent connection. The response should still terminate since a 204
446// cannot have a response body.
447TEST_F(HttpNetworkTransactionTest, StopsReading204) {
448 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35449 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
450 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42451 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17452 };
[email protected]31a2bfe2010-02-09 08:03:39453 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
454 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42455 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17456 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
457 EXPECT_EQ("", out.response_data);
458}
459
[email protected]0877e3d2009-10-17 22:29:57460// A simple request using chunked encoding with some extra data after.
461// (Like might be seen in a pipelined response.)
462TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
463 MockRead data_reads[] = {
464 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
465 MockRead("5\r\nHello\r\n"),
466 MockRead("1\r\n"),
467 MockRead(" \r\n"),
468 MockRead("5\r\nworld\r\n"),
469 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
470 MockRead(false, OK),
471 };
[email protected]31a2bfe2010-02-09 08:03:39472 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
473 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57474 EXPECT_EQ(OK, out.rv);
475 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
476 EXPECT_EQ("Hello world", out.response_data);
477}
478
[email protected]ef0faf2e72009-03-05 23:27:23479// Do a request using the HEAD method. Verify that we don't try to read the
480// message body (since HEAD has none).
481TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59482 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40483 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43484 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23485
[email protected]1c773ea12009-04-28 19:58:42486 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23487 request.method = "HEAD";
488 request.url = GURL("http://www.google.com/");
489 request.load_flags = 0;
490
491 MockWrite data_writes1[] = {
492 MockWrite("HEAD / HTTP/1.1\r\n"
493 "Host: www.google.com\r\n"
494 "Connection: keep-alive\r\n"
495 "Content-Length: 0\r\n\r\n"),
496 };
497 MockRead data_reads1[] = {
498 MockRead("HTTP/1.1 404 Not Found\r\n"),
499 MockRead("Server: Blah\r\n"),
500 MockRead("Content-Length: 1234\r\n\r\n"),
501
502 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42503 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23504 };
505
[email protected]31a2bfe2010-02-09 08:03:39506 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
507 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59508 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23509
510 TestCompletionCallback callback1;
511
[email protected]5a1d7ca2010-04-28 20:12:27512 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42513 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23514
515 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42516 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23517
[email protected]1c773ea12009-04-28 19:58:42518 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23519 EXPECT_FALSE(response == NULL);
520
521 // Check that the headers got parsed.
522 EXPECT_TRUE(response->headers != NULL);
523 EXPECT_EQ(1234, response->headers->GetContentLength());
524 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
525
526 std::string server_header;
527 void* iter = NULL;
528 bool has_server_header = response->headers->EnumerateHeader(
529 &iter, "Server", &server_header);
530 EXPECT_TRUE(has_server_header);
531 EXPECT_EQ("Blah", server_header);
532
533 // Reading should give EOF right away, since there is no message body
534 // (despite non-zero content-length).
535 std::string response_data;
536 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42537 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23538 EXPECT_EQ("", response_data);
539}
540
initial.commit586acc5fe2008-07-26 22:42:52541TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59542 SessionDependencies session_deps;
543 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52544
545 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35546 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
547 MockRead("hello"),
548 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
549 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42550 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52551 };
[email protected]31a2bfe2010-02-09 08:03:39552 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59553 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52554
555 const char* kExpectedResponseData[] = {
556 "hello", "world"
557 };
558
559 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43560 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52561
[email protected]1c773ea12009-04-28 19:58:42562 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52563 request.method = "GET";
564 request.url = GURL("http://www.google.com/");
565 request.load_flags = 0;
566
567 TestCompletionCallback callback;
568
[email protected]5a1d7ca2010-04-28 20:12:27569 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42570 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52571
572 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42573 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52574
[email protected]1c773ea12009-04-28 19:58:42575 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52576 EXPECT_TRUE(response != NULL);
577
578 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25579 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52580
581 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57582 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42583 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25584 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52585 }
586}
587
588TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59589 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40590 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43591 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52592
[email protected]1c773ea12009-04-28 19:58:42593 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52594 request.method = "POST";
595 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42596 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52597 request.upload_data->AppendBytes("foo", 3);
598 request.load_flags = 0;
599
600 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35601 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
602 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
603 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42604 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52605 };
[email protected]31a2bfe2010-02-09 08:03:39606 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59607 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52608
609 TestCompletionCallback callback;
610
[email protected]5a1d7ca2010-04-28 20:12:27611 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42612 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52613
614 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42615 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52616
[email protected]1c773ea12009-04-28 19:58:42617 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52618 EXPECT_TRUE(response != NULL);
619
620 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25621 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52622
623 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57624 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42625 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25626 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52627}
628
[email protected]3a2d3662009-03-27 03:49:14629// This test is almost the same as Ignores100 above, but the response contains
630// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57631// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14632TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59633 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40634 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43635 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14636
[email protected]1c773ea12009-04-28 19:58:42637 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14638 request.method = "GET";
639 request.url = GURL("http://www.foo.com/");
640 request.load_flags = 0;
641
642 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57643 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
644 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14645 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42646 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14647 };
[email protected]31a2bfe2010-02-09 08:03:39648 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59649 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14650
651 TestCompletionCallback callback;
652
[email protected]5a1d7ca2010-04-28 20:12:27653 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42654 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14655
656 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42657 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14658
[email protected]1c773ea12009-04-28 19:58:42659 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14660 EXPECT_TRUE(response != NULL);
661
662 EXPECT_TRUE(response->headers != NULL);
663 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
664
665 std::string response_data;
666 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42667 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14668 EXPECT_EQ("hello world", response_data);
669}
670
[email protected]ee9410e72010-01-07 01:42:38671TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
672 SessionDependencies session_deps;
673 scoped_ptr<HttpTransaction> trans(
674 new HttpNetworkTransaction(CreateSession(&session_deps)));
675
676 HttpRequestInfo request;
677 request.method = "POST";
678 request.url = GURL("http://www.foo.com/");
679 request.load_flags = 0;
680
681 MockRead data_reads[] = {
682 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
683 MockRead(true, 0),
684 };
[email protected]31a2bfe2010-02-09 08:03:39685 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38686 session_deps.socket_factory.AddSocketDataProvider(&data);
687
688 TestCompletionCallback callback;
689
[email protected]5a1d7ca2010-04-28 20:12:27690 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38691 EXPECT_EQ(ERR_IO_PENDING, rv);
692
693 rv = callback.WaitForResult();
694 EXPECT_EQ(OK, rv);
695
696 std::string response_data;
697 rv = ReadTransaction(trans.get(), &response_data);
698 EXPECT_EQ(OK, rv);
699 EXPECT_EQ("", response_data);
700}
701
702TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
703 SessionDependencies session_deps;
704 scoped_ptr<HttpTransaction> trans(
705 new HttpNetworkTransaction(CreateSession(&session_deps)));
706
707 HttpRequestInfo request;
708 request.method = "POST";
709 request.url = GURL("http://www.foo.com/");
710 request.load_flags = 0;
711
712 MockRead data_reads[] = {
713 MockRead(true, 0),
714 };
[email protected]31a2bfe2010-02-09 08:03:39715 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38716 session_deps.socket_factory.AddSocketDataProvider(&data);
717
718 TestCompletionCallback callback;
719
[email protected]5a1d7ca2010-04-28 20:12:27720 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38721 EXPECT_EQ(ERR_IO_PENDING, rv);
722
723 rv = callback.WaitForResult();
724 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
725}
726
[email protected]3d2a59b2008-09-26 19:44:25727// read_failure specifies a read failure that should cause the network
728// transaction to resend the request.
729void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
730 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59731 SessionDependencies session_deps;
732 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52733
[email protected]1c773ea12009-04-28 19:58:42734 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52735 request.method = "GET";
736 request.url = GURL("http://www.foo.com/");
737 request.load_flags = 0;
738
739 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35740 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
741 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25742 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52743 };
[email protected]31a2bfe2010-02-09 08:03:39744 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59745 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52746
747 MockRead data2_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("world"),
[email protected]1c773ea12009-04-28 19:58:42750 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52751 };
[email protected]31a2bfe2010-02-09 08:03:39752 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59753 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52754
755 const char* kExpectedResponseData[] = {
756 "hello", "world"
757 };
758
759 for (int i = 0; i < 2; ++i) {
760 TestCompletionCallback callback;
761
[email protected]5695b8c2009-09-30 21:36:43762 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52763
[email protected]5a1d7ca2010-04-28 20:12:27764 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42765 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52766
767 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42768 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52769
[email protected]1c773ea12009-04-28 19:58:42770 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52771 EXPECT_TRUE(response != NULL);
772
773 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25774 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52775
776 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57777 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42778 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25779 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52780 }
781}
[email protected]3d2a59b2008-09-26 19:44:25782
783TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42784 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25785 KeepAliveConnectionResendRequestTest(read_failure);
786}
787
788TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42789 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25790 KeepAliveConnectionResendRequestTest(read_failure);
791}
792
793TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59794 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40795 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43796 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25797
[email protected]1c773ea12009-04-28 19:58:42798 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25799 request.method = "GET";
800 request.url = GURL("http://www.google.com/");
801 request.load_flags = 0;
802
803 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42804 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35805 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
806 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42807 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25808 };
[email protected]31a2bfe2010-02-09 08:03:39809 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59810 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25811
812 TestCompletionCallback callback;
813
[email protected]5a1d7ca2010-04-28 20:12:27814 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42815 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25816
817 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42818 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25819
[email protected]1c773ea12009-04-28 19:58:42820 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25821 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25822}
823
824// What do various browsers do when the server closes a non-keepalive
825// connection without sending any response header or body?
826//
827// IE7: error page
828// Safari 3.1.2 (Windows): error page
829// Firefox 3.0.1: blank page
830// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42831// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
832// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25833TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
834 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42835 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35836 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
837 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42838 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25839 };
[email protected]31a2bfe2010-02-09 08:03:39840 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
841 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42842 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25843}
[email protected]038e9a32008-10-08 22:40:16844
[email protected]fc31d6a42010-06-24 18:05:13845// Test that we correctly reuse a keep-alive connection after receiving a 304.
846TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
847 SessionDependencies session_deps;
848 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
849
850 HttpRequestInfo request;
851 request.method = "GET";
852 request.url = GURL("http://www.foo.com/");
853 request.load_flags = 0;
854
855 MockRead data1_reads[] = {
856 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
857 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
858 MockRead("hello"),
859 };
860 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
861 session_deps.socket_factory.AddSocketDataProvider(&data1);
862
863 MockRead data2_reads[] = {
864 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
865 };
866 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
867 session_deps.socket_factory.AddSocketDataProvider(&data2);
868
869 for (int i = 0; i < 2; ++i) {
870 TestCompletionCallback callback;
871
872 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
873
874 int rv = trans->Start(&request, &callback, BoundNetLog());
875 EXPECT_EQ(ERR_IO_PENDING, rv);
876
877 rv = callback.WaitForResult();
878 EXPECT_EQ(OK, rv);
879
880 const HttpResponseInfo* response = trans->GetResponseInfo();
881 EXPECT_TRUE(response != NULL);
882
883 EXPECT_TRUE(response->headers != NULL);
884 if (i == 0) {
885 EXPECT_EQ("HTTP/1.1 304 Not Modified",
886 response->headers->GetStatusLine());
887 // We intentionally don't read the response in this case, to reflect how
888 // HttpCache::Transaction uses HttpNetworkTransaction.
889 } else {
890 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
891 std::string response_data;
892 rv = ReadTransaction(trans.get(), &response_data);
893 EXPECT_EQ(OK, rv);
894 EXPECT_EQ("hello", response_data);
895 }
896 }
897}
898
[email protected]038e9a32008-10-08 22:40:16899// Test the request-challenge-retry sequence for basic auth.
900// (basic auth is the easiest to mock, because it has no randomness).
901TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59902 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40903 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43904 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16905
[email protected]1c773ea12009-04-28 19:58:42906 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16907 request.method = "GET";
908 request.url = GURL("http://www.google.com/");
909 request.load_flags = 0;
910
[email protected]f9ee6b52008-11-08 06:46:23911 MockWrite data_writes1[] = {
912 MockWrite("GET / HTTP/1.1\r\n"
913 "Host: www.google.com\r\n"
914 "Connection: keep-alive\r\n\r\n"),
915 };
916
[email protected]038e9a32008-10-08 22:40:16917 MockRead data_reads1[] = {
918 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
919 // Give a couple authenticate options (only the middle one is actually
920 // supported).
[email protected]22927ad2009-09-21 19:56:19921 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16922 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
923 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
924 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
925 // Large content-length -- won't matter, as connection will be reset.
926 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42927 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16928 };
929
930 // After calling trans->RestartWithAuth(), this is the request we should
931 // be issuing -- the final header line contains the credentials.
932 MockWrite data_writes2[] = {
933 MockWrite("GET / HTTP/1.1\r\n"
934 "Host: www.google.com\r\n"
935 "Connection: keep-alive\r\n"
936 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
937 };
938
939 // Lastly, the server responds with the actual content.
940 MockRead data_reads2[] = {
941 MockRead("HTTP/1.0 200 OK\r\n"),
942 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
943 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42944 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16945 };
946
[email protected]31a2bfe2010-02-09 08:03:39947 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
948 data_writes1, arraysize(data_writes1));
949 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
950 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59951 session_deps.socket_factory.AddSocketDataProvider(&data1);
952 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16953
954 TestCompletionCallback callback1;
955
[email protected]5a1d7ca2010-04-28 20:12:27956 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42957 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16958
959 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42960 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16961
[email protected]1c773ea12009-04-28 19:58:42962 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16963 EXPECT_FALSE(response == NULL);
964
965 // The password prompt info should have been set in response->auth_challenge.
966 EXPECT_FALSE(response->auth_challenge.get() == NULL);
967
[email protected]71e4573a2009-05-21 22:03:00968 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16969 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
970 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
971
972 TestCompletionCallback callback2;
973
[email protected]13c8a092010-07-29 06:15:44974 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:42975 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16976
977 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42978 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16979
980 response = trans->GetResponseInfo();
981 EXPECT_FALSE(response == NULL);
982 EXPECT_TRUE(response->auth_challenge.get() == NULL);
983 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16984}
985
[email protected]861fcd52009-08-26 02:33:46986TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
987 SessionDependencies session_deps;
988 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43989 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46990
991 HttpRequestInfo request;
992 request.method = "GET";
993 request.url = GURL("http://www.google.com/");
994 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
995
996 MockWrite data_writes[] = {
997 MockWrite("GET / HTTP/1.1\r\n"
998 "Host: www.google.com\r\n"
999 "Connection: keep-alive\r\n\r\n"),
1000 };
1001
1002 MockRead data_reads[] = {
1003 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1004 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1005 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1006 // Large content-length -- won't matter, as connection will be reset.
1007 MockRead("Content-Length: 10000\r\n\r\n"),
1008 MockRead(false, ERR_FAILED),
1009 };
1010
[email protected]31a2bfe2010-02-09 08:03:391011 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1012 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591013 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461014 TestCompletionCallback callback;
1015
[email protected]5a1d7ca2010-04-28 20:12:271016 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461017 EXPECT_EQ(ERR_IO_PENDING, rv);
1018
1019 rv = callback.WaitForResult();
1020 EXPECT_EQ(0, rv);
1021
1022 const HttpResponseInfo* response = trans->GetResponseInfo();
1023 ASSERT_FALSE(response == NULL);
1024 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1025}
1026
[email protected]2d2697f92009-02-18 21:00:321027// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1028// connection.
1029TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591030 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401031 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431032 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321033
[email protected]1c773ea12009-04-28 19:58:421034 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321035 request.method = "GET";
1036 request.url = GURL("http://www.google.com/");
1037 request.load_flags = 0;
1038
1039 MockWrite data_writes1[] = {
1040 MockWrite("GET / HTTP/1.1\r\n"
1041 "Host: www.google.com\r\n"
1042 "Connection: keep-alive\r\n\r\n"),
1043
1044 // After calling trans->RestartWithAuth(), this is the request we should
1045 // be issuing -- the final header line contains the credentials.
1046 MockWrite("GET / HTTP/1.1\r\n"
1047 "Host: www.google.com\r\n"
1048 "Connection: keep-alive\r\n"
1049 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1050 };
1051
1052 MockRead data_reads1[] = {
1053 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1054 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1055 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1056 MockRead("Content-Length: 14\r\n\r\n"),
1057 MockRead("Unauthorized\r\n"),
1058
1059 // Lastly, the server responds with the actual content.
1060 MockRead("HTTP/1.1 200 OK\r\n"),
1061 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1062 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421063 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321064 };
1065
[email protected]31a2bfe2010-02-09 08:03:391066 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1067 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591068 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321069
1070 TestCompletionCallback callback1;
1071
[email protected]5a1d7ca2010-04-28 20:12:271072 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421073 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321074
1075 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421076 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321077
[email protected]1c773ea12009-04-28 19:58:421078 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321079 EXPECT_FALSE(response == NULL);
1080
1081 // The password prompt info should have been set in response->auth_challenge.
1082 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1083
[email protected]71e4573a2009-05-21 22:03:001084 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321085 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1086 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1087
1088 TestCompletionCallback callback2;
1089
[email protected]13c8a092010-07-29 06:15:441090 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421091 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321092
1093 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421094 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321095
1096 response = trans->GetResponseInfo();
1097 EXPECT_FALSE(response == NULL);
1098 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1099 EXPECT_EQ(100, response->headers->GetContentLength());
1100}
1101
1102// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1103// connection and with no response body to drain.
1104TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591105 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401106 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431107 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321108
[email protected]1c773ea12009-04-28 19:58:421109 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321110 request.method = "GET";
1111 request.url = GURL("http://www.google.com/");
1112 request.load_flags = 0;
1113
1114 MockWrite data_writes1[] = {
1115 MockWrite("GET / HTTP/1.1\r\n"
1116 "Host: www.google.com\r\n"
1117 "Connection: keep-alive\r\n\r\n"),
1118
1119 // After calling trans->RestartWithAuth(), this is the request we should
1120 // be issuing -- the final header line contains the credentials.
1121 MockWrite("GET / HTTP/1.1\r\n"
1122 "Host: www.google.com\r\n"
1123 "Connection: keep-alive\r\n"
1124 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1125 };
1126
[email protected]2d2697f92009-02-18 21:00:321127 MockRead data_reads1[] = {
1128 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1129 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311130 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321131
1132 // Lastly, the server responds with the actual content.
1133 MockRead("HTTP/1.1 200 OK\r\n"),
1134 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1135 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421136 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321137 };
1138
[email protected]31a2bfe2010-02-09 08:03:391139 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1140 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591141 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321142
1143 TestCompletionCallback callback1;
1144
[email protected]5a1d7ca2010-04-28 20:12:271145 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421146 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321147
1148 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421149 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321150
[email protected]1c773ea12009-04-28 19:58:421151 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321152 EXPECT_FALSE(response == NULL);
1153
1154 // The password prompt info should have been set in response->auth_challenge.
1155 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1156
[email protected]71e4573a2009-05-21 22:03:001157 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321158 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1159 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1160
1161 TestCompletionCallback callback2;
1162
[email protected]13c8a092010-07-29 06:15:441163 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421164 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321165
1166 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421167 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321168
1169 response = trans->GetResponseInfo();
1170 EXPECT_FALSE(response == NULL);
1171 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1172 EXPECT_EQ(100, response->headers->GetContentLength());
1173}
1174
1175// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1176// connection and with a large response body to drain.
1177TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591178 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401179 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431180 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321181
[email protected]1c773ea12009-04-28 19:58:421182 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321183 request.method = "GET";
1184 request.url = GURL("http://www.google.com/");
1185 request.load_flags = 0;
1186
1187 MockWrite data_writes1[] = {
1188 MockWrite("GET / HTTP/1.1\r\n"
1189 "Host: www.google.com\r\n"
1190 "Connection: keep-alive\r\n\r\n"),
1191
1192 // After calling trans->RestartWithAuth(), this is the request we should
1193 // be issuing -- the final header line contains the credentials.
1194 MockWrite("GET / HTTP/1.1\r\n"
1195 "Host: www.google.com\r\n"
1196 "Connection: keep-alive\r\n"
1197 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1198 };
1199
1200 // Respond with 5 kb of response body.
1201 std::string large_body_string("Unauthorized");
1202 large_body_string.append(5 * 1024, ' ');
1203 large_body_string.append("\r\n");
1204
1205 MockRead data_reads1[] = {
1206 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1207 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1208 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1209 // 5134 = 12 + 5 * 1024 + 2
1210 MockRead("Content-Length: 5134\r\n\r\n"),
1211 MockRead(true, large_body_string.data(), large_body_string.size()),
1212
1213 // Lastly, the server responds with the actual content.
1214 MockRead("HTTP/1.1 200 OK\r\n"),
1215 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1216 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421217 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321218 };
1219
[email protected]31a2bfe2010-02-09 08:03:391220 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1221 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591222 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321223
1224 TestCompletionCallback callback1;
1225
[email protected]5a1d7ca2010-04-28 20:12:271226 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421227 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321228
1229 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421230 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321231
[email protected]1c773ea12009-04-28 19:58:421232 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321233 EXPECT_FALSE(response == NULL);
1234
1235 // The password prompt info should have been set in response->auth_challenge.
1236 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1237
[email protected]71e4573a2009-05-21 22:03:001238 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321239 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1240 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1241
1242 TestCompletionCallback callback2;
1243
[email protected]13c8a092010-07-29 06:15:441244 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421245 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321246
1247 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421248 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321249
1250 response = trans->GetResponseInfo();
1251 EXPECT_FALSE(response == NULL);
1252 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1253 EXPECT_EQ(100, response->headers->GetContentLength());
1254}
1255
1256// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311257// connection, but the server gets impatient and closes the connection.
1258TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1259 SessionDependencies session_deps;
1260 scoped_ptr<HttpTransaction> trans(
1261 new HttpNetworkTransaction(CreateSession(&session_deps)));
1262
1263 HttpRequestInfo request;
1264 request.method = "GET";
1265 request.url = GURL("http://www.google.com/");
1266 request.load_flags = 0;
1267
1268 MockWrite data_writes1[] = {
1269 MockWrite("GET / HTTP/1.1\r\n"
1270 "Host: www.google.com\r\n"
1271 "Connection: keep-alive\r\n\r\n"),
1272 // This simulates the seemingly successful write to a closed connection
1273 // if the bug is not fixed.
1274 MockWrite("GET / HTTP/1.1\r\n"
1275 "Host: www.google.com\r\n"
1276 "Connection: keep-alive\r\n"
1277 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1278 };
1279
1280 MockRead data_reads1[] = {
1281 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1282 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1283 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1284 MockRead("Content-Length: 14\r\n\r\n"),
1285 // Tell MockTCPClientSocket to simulate the server closing the connection.
1286 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1287 MockRead("Unauthorized\r\n"),
1288 MockRead(false, OK), // The server closes the connection.
1289 };
1290
1291 // After calling trans->RestartWithAuth(), this is the request we should
1292 // be issuing -- the final header line contains the credentials.
1293 MockWrite data_writes2[] = {
1294 MockWrite("GET / HTTP/1.1\r\n"
1295 "Host: www.google.com\r\n"
1296 "Connection: keep-alive\r\n"
1297 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1298 };
1299
1300 // Lastly, the server responds with the actual content.
1301 MockRead data_reads2[] = {
1302 MockRead("HTTP/1.1 200 OK\r\n"),
1303 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1304 MockRead("Content-Length: 100\r\n\r\n"),
1305 MockRead(false, OK),
1306 };
1307
[email protected]31a2bfe2010-02-09 08:03:391308 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1309 data_writes1, arraysize(data_writes1));
1310 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1311 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311312 session_deps.socket_factory.AddSocketDataProvider(&data1);
1313 session_deps.socket_factory.AddSocketDataProvider(&data2);
1314
1315 TestCompletionCallback callback1;
1316
[email protected]5a1d7ca2010-04-28 20:12:271317 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311318 EXPECT_EQ(ERR_IO_PENDING, rv);
1319
1320 rv = callback1.WaitForResult();
1321 EXPECT_EQ(OK, rv);
1322
1323 const HttpResponseInfo* response = trans->GetResponseInfo();
1324 EXPECT_FALSE(response == NULL);
1325
1326 // The password prompt info should have been set in response->auth_challenge.
1327 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1328
1329 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1330 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1331 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1332
1333 TestCompletionCallback callback2;
1334
[email protected]13c8a092010-07-29 06:15:441335 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311336 EXPECT_EQ(ERR_IO_PENDING, rv);
1337
1338 rv = callback2.WaitForResult();
1339 EXPECT_EQ(OK, rv);
1340
1341 response = trans->GetResponseInfo();
1342 ASSERT_FALSE(response == NULL);
1343 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1344 EXPECT_EQ(100, response->headers->GetContentLength());
1345}
1346
[email protected]394816e92010-08-03 07:38:591347// Test the request-challenge-retry sequence for basic auth, over a connection
1348// that requires a restart when setting up an SSL tunnel.
1349TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1350 // Configure against proxy server "myproxy:70".
1351 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1352 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1353 session_deps.net_log = log.bound().net_log();
1354 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1355
1356 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1357
1358 HttpRequestInfo request;
1359 request.method = "GET";
1360 request.url = GURL("https://www.google.com/");
1361 // when the no authentication data flag is set.
1362 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1363
1364 // Since we have proxy, should try to establish tunnel.
1365 MockWrite data_writes1[] = {
1366 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1367 "Host: www.google.com\r\n"
1368 "Proxy-Connection: keep-alive\r\n\r\n"),
1369
1370 // After calling trans->RestartWithAuth(), this is the request we should
1371 // be issuing -- the final header line contains the credentials.
1372 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1373 "Host: www.google.com\r\n"
1374 "Proxy-Connection: keep-alive\r\n"
1375 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1376
1377 MockWrite("GET / HTTP/1.1\r\n"
1378 "Host: www.google.com\r\n"
1379 "Connection: keep-alive\r\n\r\n"),
1380 };
1381
1382 // The proxy responds to the connect with a 407, using a persistent
1383 // connection.
1384 MockRead data_reads1[] = {
1385 // No credentials.
1386 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1387 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1388 MockRead("Proxy-Connection: close\r\n\r\n"),
1389
1390 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1391
1392 MockRead("HTTP/1.1 200 OK\r\n"),
1393 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1394 MockRead("Content-Length: 100\r\n\r\n"),
1395 MockRead(false, OK),
1396 };
1397
1398 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1399 data_writes1, arraysize(data_writes1));
1400 session_deps.socket_factory.AddSocketDataProvider(&data1);
1401 SSLSocketDataProvider ssl(true, OK);
1402 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1403
1404 TestCompletionCallback callback1;
1405
1406 int rv = trans->Start(&request, &callback1, log.bound());
1407 EXPECT_EQ(ERR_IO_PENDING, rv);
1408
1409 rv = callback1.WaitForResult();
1410 EXPECT_EQ(OK, rv);
1411 size_t pos = ExpectLogContainsSomewhere(
1412 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1413 NetLog::PHASE_NONE);
1414 ExpectLogContainsSomewhere(
1415 log.entries(), pos,
1416 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1417 NetLog::PHASE_NONE);
1418
1419 const HttpResponseInfo* response = trans->GetResponseInfo();
1420 ASSERT_FALSE(response == NULL);
1421
1422 EXPECT_EQ(407, response->headers->response_code());
1423 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1424
1425 // The password prompt info should have been set in response->auth_challenge.
1426 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1427
1428 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1429 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1430 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1431
1432 TestCompletionCallback callback2;
1433
1434 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1435 EXPECT_EQ(ERR_IO_PENDING, rv);
1436
1437 rv = callback2.WaitForResult();
1438 EXPECT_EQ(OK, rv);
1439
1440 response = trans->GetResponseInfo();
1441 ASSERT_FALSE(response == NULL);
1442
1443 EXPECT_TRUE(response->headers->IsKeepAlive());
1444 EXPECT_EQ(200, response->headers->response_code());
1445 EXPECT_EQ(100, response->headers->GetContentLength());
1446 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1447
1448 // The password prompt info should not be set.
1449 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1450}
1451
[email protected]11203f012009-11-12 23:02:311452// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321453// proxy connection, when setting up an SSL tunnel.
1454TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1455 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591456 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541457 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1458 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591459 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321460
[email protected]5695b8c2009-09-30 21:36:431461 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321462
[email protected]1c773ea12009-04-28 19:58:421463 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321464 request.method = "GET";
1465 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461466 // Ensure that proxy authentication is attempted even
1467 // when the no authentication data flag is set.
1468 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321469
1470 // Since we have proxy, should try to establish tunnel.
1471 MockWrite data_writes1[] = {
1472 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451473 "Host: www.google.com\r\n"
1474 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321475
1476 // After calling trans->RestartWithAuth(), this is the request we should
1477 // be issuing -- the final header line contains the credentials.
1478 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1479 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451480 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321481 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1482 };
1483
1484 // The proxy responds to the connect with a 407, using a persistent
1485 // connection.
1486 MockRead data_reads1[] = {
1487 // No credentials.
1488 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1489 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1490 MockRead("Content-Length: 10\r\n\r\n"),
1491 MockRead("0123456789"),
1492
1493 // Wrong credentials (wrong password).
1494 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1495 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1496 MockRead("Content-Length: 10\r\n\r\n"),
1497 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421498 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321499 };
1500
[email protected]31a2bfe2010-02-09 08:03:391501 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1502 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591503 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321504
1505 TestCompletionCallback callback1;
1506
[email protected]dbb83db2010-05-11 18:13:391507 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421508 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321509
1510 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421511 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391512 size_t pos = ExpectLogContainsSomewhere(
1513 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1514 NetLog::PHASE_NONE);
1515 ExpectLogContainsSomewhere(
1516 log.entries(), pos,
1517 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1518 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321519
[email protected]1c773ea12009-04-28 19:58:421520 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321521 EXPECT_FALSE(response == NULL);
1522
1523 EXPECT_TRUE(response->headers->IsKeepAlive());
1524 EXPECT_EQ(407, response->headers->response_code());
1525 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421526 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321527
1528 // The password prompt info should have been set in response->auth_challenge.
1529 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1530
[email protected]71e4573a2009-05-21 22:03:001531 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321532 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1533 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1534
1535 TestCompletionCallback callback2;
1536
1537 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441538 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421539 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321540
1541 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421542 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321543
1544 response = trans->GetResponseInfo();
1545 EXPECT_FALSE(response == NULL);
1546
1547 EXPECT_TRUE(response->headers->IsKeepAlive());
1548 EXPECT_EQ(407, response->headers->response_code());
1549 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421550 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321551
1552 // The password prompt info should have been set in response->auth_challenge.
1553 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1554
[email protected]71e4573a2009-05-21 22:03:001555 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321556 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1557 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131558
[email protected]e60e47a2010-07-14 03:37:181559 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1560 // out of scope.
1561 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321562}
1563
[email protected]a8e9b162009-03-12 00:06:441564// Test that we don't read the response body when we fail to establish a tunnel,
1565// even if the user cancels the proxy's auth attempt.
1566TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1567 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591568 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441569
[email protected]e44de5d2009-06-05 20:12:451570 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441571
[email protected]5695b8c2009-09-30 21:36:431572 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441573
[email protected]1c773ea12009-04-28 19:58:421574 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441575 request.method = "GET";
1576 request.url = GURL("https://www.google.com/");
1577 request.load_flags = 0;
1578
1579 // Since we have proxy, should try to establish tunnel.
1580 MockWrite data_writes[] = {
1581 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451582 "Host: www.google.com\r\n"
1583 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441584 };
1585
1586 // The proxy responds to the connect with a 407.
1587 MockRead data_reads[] = {
1588 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1589 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1590 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421591 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441592 };
1593
[email protected]31a2bfe2010-02-09 08:03:391594 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1595 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591596 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441597
1598 TestCompletionCallback callback;
1599
[email protected]5a1d7ca2010-04-28 20:12:271600 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421601 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441602
1603 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421604 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441605
[email protected]1c773ea12009-04-28 19:58:421606 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441607 EXPECT_FALSE(response == NULL);
1608
1609 EXPECT_TRUE(response->headers->IsKeepAlive());
1610 EXPECT_EQ(407, response->headers->response_code());
1611 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421612 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441613
1614 std::string response_data;
1615 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421616 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181617
1618 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1619 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441620}
1621
[email protected]8fdbcd22010-05-05 02:54:521622// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1623// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1624TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1625 // We are using a DIRECT connection (i.e. no proxy) for this session.
1626 SessionDependencies session_deps;
1627 scoped_ptr<HttpTransaction> trans(
1628 new HttpNetworkTransaction(CreateSession(&session_deps)));
1629
1630 HttpRequestInfo request;
1631 request.method = "GET";
1632 request.url = GURL("http://www.google.com/");
1633 request.load_flags = 0;
1634
1635 MockWrite data_writes1[] = {
1636 MockWrite("GET / HTTP/1.1\r\n"
1637 "Host: www.google.com\r\n"
1638 "Connection: keep-alive\r\n\r\n"),
1639 };
1640
1641 MockRead data_reads1[] = {
1642 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1643 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1644 // Large content-length -- won't matter, as connection will be reset.
1645 MockRead("Content-Length: 10000\r\n\r\n"),
1646 MockRead(false, ERR_FAILED),
1647 };
1648
1649 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1650 data_writes1, arraysize(data_writes1));
1651 session_deps.socket_factory.AddSocketDataProvider(&data1);
1652
1653 TestCompletionCallback callback;
1654
1655 int rv = trans->Start(&request, &callback, BoundNetLog());
1656 EXPECT_EQ(ERR_IO_PENDING, rv);
1657
1658 rv = callback.WaitForResult();
1659 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1660}
1661
[email protected]ff007e162009-05-23 09:13:151662void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081663 const MockRead& status, int expected_status) {
1664 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591665 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081666
[email protected]228ff742009-06-05 01:19:591667 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081668
[email protected]5695b8c2009-09-30 21:36:431669 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081670
[email protected]1c773ea12009-04-28 19:58:421671 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081672 request.method = "GET";
1673 request.url = GURL("https://www.google.com/");
1674 request.load_flags = 0;
1675
1676 // Since we have proxy, should try to establish tunnel.
1677 MockWrite data_writes[] = {
1678 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451679 "Host: www.google.com\r\n"
1680 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081681 };
1682
1683 MockRead data_reads[] = {
1684 status,
1685 MockRead("Content-Length: 10\r\n\r\n"),
1686 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421687 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081688 };
1689
[email protected]31a2bfe2010-02-09 08:03:391690 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1691 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591692 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081693
1694 TestCompletionCallback callback;
1695
[email protected]5a1d7ca2010-04-28 20:12:271696 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081698
1699 rv = callback.WaitForResult();
1700 EXPECT_EQ(expected_status, rv);
1701}
1702
[email protected]ff007e162009-05-23 09:13:151703void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081704 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421705 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081706}
1707
1708TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1709 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1710}
1711
1712TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1713 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1714}
1715
1716TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1717 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1718}
1719
1720TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1721 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1722}
1723
1724TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1725 ConnectStatusHelper(
1726 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1727}
1728
1729TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1730 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1731}
1732
1733TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1734 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1735}
1736
1737TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1738 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1739}
1740
1741TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1742 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1743}
1744
1745TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1746 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1747}
1748
1749TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1750 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1751}
1752
1753TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1754 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1755}
1756
1757TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1758 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1759}
1760
1761TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1762 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1763}
1764
1765TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1766 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1767}
1768
1769TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1770 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1771}
1772
1773TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1774 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1775}
1776
1777TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1778 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1779}
1780
1781TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1782 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1783}
1784
1785TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1786 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1787}
1788
1789TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1790 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1791}
1792
1793TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1794 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1795}
1796
1797TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1798 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1799}
1800
1801TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1802 ConnectStatusHelperWithExpectedStatus(
1803 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541804 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081805}
1806
1807TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1808 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1809}
1810
1811TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1812 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1813}
1814
1815TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1816 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1817}
1818
1819TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1820 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1821}
1822
1823TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1824 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1825}
1826
1827TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1828 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1829}
1830
1831TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1832 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1833}
1834
1835TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1836 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1837}
1838
1839TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1840 ConnectStatusHelper(
1841 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1842}
1843
1844TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1845 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1846}
1847
1848TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1849 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1850}
1851
1852TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1853 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1854}
1855
1856TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1857 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1858}
1859
1860TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1861 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1862}
1863
1864TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1865 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1866}
1867
1868TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1869 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1870}
1871
[email protected]038e9a32008-10-08 22:40:161872// Test the flow when both the proxy server AND origin server require
1873// authentication. Again, this uses basic auth for both since that is
1874// the simplest to mock.
1875TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591876 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011877
[email protected]038e9a32008-10-08 22:40:161878 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421879 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431880 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161881
[email protected]1c773ea12009-04-28 19:58:421882 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161883 request.method = "GET";
1884 request.url = GURL("http://www.google.com/");
1885 request.load_flags = 0;
1886
[email protected]f9ee6b52008-11-08 06:46:231887 MockWrite data_writes1[] = {
1888 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1889 "Host: www.google.com\r\n"
1890 "Proxy-Connection: keep-alive\r\n\r\n"),
1891 };
1892
[email protected]038e9a32008-10-08 22:40:161893 MockRead data_reads1[] = {
1894 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1895 // Give a couple authenticate options (only the middle one is actually
1896 // supported).
[email protected]22927ad2009-09-21 19:56:191897 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161898 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1899 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1900 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1901 // Large content-length -- won't matter, as connection will be reset.
1902 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421903 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161904 };
1905
1906 // After calling trans->RestartWithAuth() the first time, this is the
1907 // request we should be issuing -- the final header line contains the
1908 // proxy's credentials.
1909 MockWrite data_writes2[] = {
1910 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1911 "Host: www.google.com\r\n"
1912 "Proxy-Connection: keep-alive\r\n"
1913 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1914 };
1915
1916 // Now the proxy server lets the request pass through to origin server.
1917 // The origin server responds with a 401.
1918 MockRead data_reads2[] = {
1919 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1920 // Note: We are using the same realm-name as the proxy server. This is
1921 // completely valid, as realms are unique across hosts.
1922 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1924 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421925 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161926 };
1927
1928 // After calling trans->RestartWithAuth() the second time, we should send
1929 // the credentials for both the proxy and origin server.
1930 MockWrite data_writes3[] = {
1931 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1932 "Host: www.google.com\r\n"
1933 "Proxy-Connection: keep-alive\r\n"
1934 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1935 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1936 };
1937
1938 // Lastly we get the desired content.
1939 MockRead data_reads3[] = {
1940 MockRead("HTTP/1.0 200 OK\r\n"),
1941 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1942 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421943 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161944 };
1945
[email protected]31a2bfe2010-02-09 08:03:391946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1947 data_writes1, arraysize(data_writes1));
1948 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1949 data_writes2, arraysize(data_writes2));
1950 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1951 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591952 session_deps.socket_factory.AddSocketDataProvider(&data1);
1953 session_deps.socket_factory.AddSocketDataProvider(&data2);
1954 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161955
1956 TestCompletionCallback callback1;
1957
[email protected]5a1d7ca2010-04-28 20:12:271958 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421959 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161960
1961 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421962 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161963
[email protected]1c773ea12009-04-28 19:58:421964 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161965 EXPECT_FALSE(response == NULL);
1966
1967 // The password prompt info should have been set in response->auth_challenge.
1968 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1969
[email protected]71e4573a2009-05-21 22:03:001970 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161971 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1972 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1973
1974 TestCompletionCallback callback2;
1975
[email protected]13c8a092010-07-29 06:15:441976 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421977 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161978
1979 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421980 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161981
1982 response = trans->GetResponseInfo();
1983 EXPECT_FALSE(response == NULL);
1984 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1985
[email protected]71e4573a2009-05-21 22:03:001986 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161987 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1988 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1989
1990 TestCompletionCallback callback3;
1991
[email protected]13c8a092010-07-29 06:15:441992 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:421993 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161994
1995 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421996 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161997
1998 response = trans->GetResponseInfo();
1999 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2000 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162001}
[email protected]4ddaf2502008-10-23 18:26:192002
[email protected]ea9dc9a2009-09-05 00:43:322003// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2004// can't hook into its internals to cause it to generate predictable NTLM
2005// authorization headers.
2006#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292007// The NTLM authentication unit tests were generated by capturing the HTTP
2008// requests and responses using Fiddler 2 and inspecting the generated random
2009// bytes in the debugger.
2010
2011// Enter the correct password and authenticate successfully.
2012TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422013 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112014 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592015 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402016 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432017 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:242018
[email protected]1c773ea12009-04-28 19:58:422019 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242020 request.method = "GET";
2021 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2022 request.load_flags = 0;
2023
2024 MockWrite data_writes1[] = {
2025 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2026 "Host: 172.22.68.17\r\n"
2027 "Connection: keep-alive\r\n\r\n"),
2028 };
2029
2030 MockRead data_reads1[] = {
2031 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042032 // Negotiate and NTLM are often requested together. However, we only want
2033 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2034 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242035 MockRead("WWW-Authenticate: NTLM\r\n"),
2036 MockRead("Connection: close\r\n"),
2037 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362038 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242039 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422040 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242041 };
2042
2043 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222044 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242045 // request we should be issuing -- the final header line contains a Type
2046 // 1 message.
2047 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2048 "Host: 172.22.68.17\r\n"
2049 "Connection: keep-alive\r\n"
2050 "Authorization: NTLM "
2051 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2052
2053 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2054 // (the credentials for the origin server). The second request continues
2055 // on the same connection.
2056 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2057 "Host: 172.22.68.17\r\n"
2058 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292059 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2060 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2061 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2062 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2063 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242064 };
2065
2066 MockRead data_reads2[] = {
2067 // The origin server responds with a Type 2 message.
2068 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2069 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292070 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242071 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2072 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2073 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2074 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2075 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2076 "BtAAAAAAA=\r\n"),
2077 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362078 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242079 MockRead("You are not authorized to view this page\r\n"),
2080
2081 // Lastly we get the desired content.
2082 MockRead("HTTP/1.1 200 OK\r\n"),
2083 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2084 MockRead("Content-Length: 13\r\n\r\n"),
2085 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422086 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242087 };
2088
[email protected]31a2bfe2010-02-09 08:03:392089 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2090 data_writes1, arraysize(data_writes1));
2091 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2092 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592093 session_deps.socket_factory.AddSocketDataProvider(&data1);
2094 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242095
2096 TestCompletionCallback callback1;
2097
[email protected]5a1d7ca2010-04-28 20:12:272098 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422099 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242100
2101 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422102 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242103
[email protected]0757e7702009-03-27 04:00:222104 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2105 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442106 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422107 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222108 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422109 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222110 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2111
[email protected]1c773ea12009-04-28 19:58:422112 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042113 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242114
[email protected]aef04272010-06-28 18:03:042115 // The password prompt info should have been set in
2116 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242117 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2118
[email protected]71e4573a2009-05-21 22:03:002119 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242120 EXPECT_EQ(L"", response->auth_challenge->realm);
2121 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2122
[email protected]0757e7702009-03-27 04:00:222123 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242124
[email protected]13c8a092010-07-29 06:15:442125 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422126 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242127
[email protected]0757e7702009-03-27 04:00:222128 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422129 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242130
2131 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042132 ASSERT_FALSE(response == NULL);
2133
[email protected]3f918782009-02-28 01:29:242134 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2135 EXPECT_EQ(13, response->headers->GetContentLength());
2136}
2137
[email protected]385a4672009-03-11 22:21:292138// Enter a wrong password, and then the correct one.
2139TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422140 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112141 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592142 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402143 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432144 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:292145
[email protected]1c773ea12009-04-28 19:58:422146 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292147 request.method = "GET";
2148 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2149 request.load_flags = 0;
2150
2151 MockWrite data_writes1[] = {
2152 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2153 "Host: 172.22.68.17\r\n"
2154 "Connection: keep-alive\r\n\r\n"),
2155 };
2156
2157 MockRead data_reads1[] = {
2158 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042159 // Negotiate and NTLM are often requested together. However, we only want
2160 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2161 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292162 MockRead("WWW-Authenticate: NTLM\r\n"),
2163 MockRead("Connection: close\r\n"),
2164 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362165 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292166 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422167 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292168 };
2169
2170 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222171 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292172 // request we should be issuing -- the final header line contains a Type
2173 // 1 message.
2174 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2175 "Host: 172.22.68.17\r\n"
2176 "Connection: keep-alive\r\n"
2177 "Authorization: NTLM "
2178 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2179
2180 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2181 // (the credentials for the origin server). The second request continues
2182 // on the same connection.
2183 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2184 "Host: 172.22.68.17\r\n"
2185 "Connection: keep-alive\r\n"
2186 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2187 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2188 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2189 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2190 "4Ww7b7E=\r\n\r\n"),
2191 };
2192
2193 MockRead data_reads2[] = {
2194 // The origin server responds with a Type 2 message.
2195 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2196 MockRead("WWW-Authenticate: NTLM "
2197 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2198 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2199 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2200 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2201 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2202 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2203 "BtAAAAAAA=\r\n"),
2204 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362205 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292206 MockRead("You are not authorized to view this page\r\n"),
2207
2208 // Wrong password.
2209 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292210 MockRead("WWW-Authenticate: NTLM\r\n"),
2211 MockRead("Connection: close\r\n"),
2212 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362213 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292214 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422215 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292216 };
2217
2218 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222219 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292220 // request we should be issuing -- the final header line contains a Type
2221 // 1 message.
2222 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2223 "Host: 172.22.68.17\r\n"
2224 "Connection: keep-alive\r\n"
2225 "Authorization: NTLM "
2226 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2227
2228 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2229 // (the credentials for the origin server). The second request continues
2230 // on the same connection.
2231 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2232 "Host: 172.22.68.17\r\n"
2233 "Connection: keep-alive\r\n"
2234 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2235 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2236 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2237 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2238 "+4MUm7c=\r\n\r\n"),
2239 };
2240
2241 MockRead data_reads3[] = {
2242 // The origin server responds with a Type 2 message.
2243 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2244 MockRead("WWW-Authenticate: NTLM "
2245 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2246 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2247 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2248 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2249 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2250 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2251 "BtAAAAAAA=\r\n"),
2252 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362253 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292254 MockRead("You are not authorized to view this page\r\n"),
2255
2256 // Lastly we get the desired content.
2257 MockRead("HTTP/1.1 200 OK\r\n"),
2258 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2259 MockRead("Content-Length: 13\r\n\r\n"),
2260 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422261 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292262 };
2263
[email protected]31a2bfe2010-02-09 08:03:392264 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2265 data_writes1, arraysize(data_writes1));
2266 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2267 data_writes2, arraysize(data_writes2));
2268 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2269 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592270 session_deps.socket_factory.AddSocketDataProvider(&data1);
2271 session_deps.socket_factory.AddSocketDataProvider(&data2);
2272 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292273
2274 TestCompletionCallback callback1;
2275
[email protected]5a1d7ca2010-04-28 20:12:272276 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422277 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292278
2279 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422280 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292281
[email protected]0757e7702009-03-27 04:00:222282 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292283 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442284 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422285 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292286 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422287 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222288 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292289
[email protected]1c773ea12009-04-28 19:58:422290 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292291 EXPECT_FALSE(response == NULL);
2292
2293 // The password prompt info should have been set in response->auth_challenge.
2294 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2295
[email protected]71e4573a2009-05-21 22:03:002296 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292297 EXPECT_EQ(L"", response->auth_challenge->realm);
2298 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2299
2300 TestCompletionCallback callback3;
2301
[email protected]0757e7702009-03-27 04:00:222302 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442303 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422304 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292305
2306 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422307 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292308
[email protected]0757e7702009-03-27 04:00:222309 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2310 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442311 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422312 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222313 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422314 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222315 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2316
2317 response = trans->GetResponseInfo();
2318 EXPECT_FALSE(response == NULL);
2319
2320 // The password prompt info should have been set in response->auth_challenge.
2321 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2322
[email protected]71e4573a2009-05-21 22:03:002323 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222324 EXPECT_EQ(L"", response->auth_challenge->realm);
2325 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2326
2327 TestCompletionCallback callback5;
2328
2329 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442330 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422331 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222332
2333 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422334 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222335
[email protected]385a4672009-03-11 22:21:292336 response = trans->GetResponseInfo();
2337 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2338 EXPECT_EQ(13, response->headers->GetContentLength());
2339}
[email protected]ea9dc9a2009-09-05 00:43:322340#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292341
[email protected]4ddaf2502008-10-23 18:26:192342// Test reading a server response which has only headers, and no body.
2343// After some maximum number of bytes is consumed, the transaction should
2344// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2345TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592346 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402347 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432348 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192349
[email protected]1c773ea12009-04-28 19:58:422350 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192351 request.method = "GET";
2352 request.url = GURL("http://www.google.com/");
2353 request.load_flags = 0;
2354
[email protected]b75b7b2f2009-10-06 00:54:532355 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432356 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532357 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192358
2359 MockRead data_reads[] = {
2360 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432361 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192362 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422363 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192364 };
[email protected]31a2bfe2010-02-09 08:03:392365 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592366 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192367
2368 TestCompletionCallback callback;
2369
[email protected]5a1d7ca2010-04-28 20:12:272370 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422371 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192372
2373 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422374 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192375
[email protected]1c773ea12009-04-28 19:58:422376 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192377 EXPECT_TRUE(response == NULL);
2378}
[email protected]f4e426b2008-11-05 00:24:492379
2380// Make sure that we don't try to reuse a TCPClientSocket when failing to
2381// establish tunnel.
2382// http://code.google.com/p/chromium/issues/detail?id=3772
2383TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2384 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592385 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012386
[email protected]228ff742009-06-05 01:19:592387 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492388
[email protected]5695b8c2009-09-30 21:36:432389 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492390
[email protected]1c773ea12009-04-28 19:58:422391 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492392 request.method = "GET";
2393 request.url = GURL("https://www.google.com/");
2394 request.load_flags = 0;
2395
2396 // Since we have proxy, should try to establish tunnel.
2397 MockWrite data_writes1[] = {
2398 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452399 "Host: www.google.com\r\n"
2400 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492401 };
2402
[email protected]77848d12008-11-14 00:00:222403 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492404 // connection. Usually a proxy would return 501 (not implemented),
2405 // or 200 (tunnel established).
2406 MockRead data_reads1[] = {
2407 MockRead("HTTP/1.1 404 Not Found\r\n"),
2408 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422409 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492410 };
2411
[email protected]31a2bfe2010-02-09 08:03:392412 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2413 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592414 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492415
2416 TestCompletionCallback callback1;
2417
[email protected]5a1d7ca2010-04-28 20:12:272418 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422419 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492420
2421 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422422 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492423
[email protected]1c773ea12009-04-28 19:58:422424 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082425 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492426
[email protected]b4404c02009-04-10 16:38:522427 // Empty the current queue. This is necessary because idle sockets are
2428 // added to the connection pool asynchronously with a PostTask.
2429 MessageLoop::current()->RunAllPending();
2430
[email protected]f4e426b2008-11-05 00:24:492431 // We now check to make sure the TCPClientSocket was not added back to
2432 // the pool.
[email protected]a937a06d2009-08-19 21:19:242433 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492434 trans.reset();
[email protected]b4404c02009-04-10 16:38:522435 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492436 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242437 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492438}
[email protected]372d34a2008-11-05 21:30:512439
[email protected]1b157c02009-04-21 01:55:402440// Make sure that we recycle a socket after reading all of the response body.
2441TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592442 SessionDependencies session_deps;
2443 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402444
[email protected]5695b8c2009-09-30 21:36:432445 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402446
[email protected]1c773ea12009-04-28 19:58:422447 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402448 request.method = "GET";
2449 request.url = GURL("http://www.google.com/");
2450 request.load_flags = 0;
2451
2452 MockRead data_reads[] = {
2453 // A part of the response body is received with the response headers.
2454 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2455 // The rest of the response body is received in two parts.
2456 MockRead("lo"),
2457 MockRead(" world"),
2458 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422459 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402460 };
2461
[email protected]31a2bfe2010-02-09 08:03:392462 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592463 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402464
2465 TestCompletionCallback callback;
2466
[email protected]5a1d7ca2010-04-28 20:12:272467 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422468 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402469
2470 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422471 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402472
[email protected]1c773ea12009-04-28 19:58:422473 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402474 EXPECT_TRUE(response != NULL);
2475
2476 EXPECT_TRUE(response->headers != NULL);
2477 std::string status_line = response->headers->GetStatusLine();
2478 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2479
[email protected]a937a06d2009-08-19 21:19:242480 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402481
2482 std::string response_data;
2483 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422484 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402485 EXPECT_EQ("hello world", response_data);
2486
2487 // Empty the current queue. This is necessary because idle sockets are
2488 // added to the connection pool asynchronously with a PostTask.
2489 MessageLoop::current()->RunAllPending();
2490
2491 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242492 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402493}
2494
[email protected]b4404c02009-04-10 16:38:522495// Make sure that we recycle a socket after a zero-length response.
2496// http://crbug.com/9880
2497TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592498 SessionDependencies session_deps;
2499 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522500
[email protected]5695b8c2009-09-30 21:36:432501 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522502
[email protected]1c773ea12009-04-28 19:58:422503 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522504 request.method = "GET";
2505 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2506 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2507 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2508 "rt=prt.2642,ol.2649,xjs.2951");
2509 request.load_flags = 0;
2510
2511 MockRead data_reads[] = {
2512 MockRead("HTTP/1.1 204 No Content\r\n"
2513 "Content-Length: 0\r\n"
2514 "Content-Type: text/html\r\n\r\n"),
2515 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422516 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522517 };
2518
[email protected]31a2bfe2010-02-09 08:03:392519 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592520 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522521
2522 TestCompletionCallback callback;
2523
[email protected]5a1d7ca2010-04-28 20:12:272524 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422525 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522526
2527 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422528 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522529
[email protected]1c773ea12009-04-28 19:58:422530 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522531 EXPECT_TRUE(response != NULL);
2532
2533 EXPECT_TRUE(response->headers != NULL);
2534 std::string status_line = response->headers->GetStatusLine();
2535 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2536
[email protected]a937a06d2009-08-19 21:19:242537 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522538
2539 std::string response_data;
2540 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422541 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522542 EXPECT_EQ("", response_data);
2543
2544 // Empty the current queue. This is necessary because idle sockets are
2545 // added to the connection pool asynchronously with a PostTask.
2546 MessageLoop::current()->RunAllPending();
2547
2548 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242549 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522550}
2551
[email protected]372d34a2008-11-05 21:30:512552TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422553 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512554 // Transaction 1: a GET request that succeeds. The socket is recycled
2555 // after use.
2556 request[0].method = "GET";
2557 request[0].url = GURL("http://www.google.com/");
2558 request[0].load_flags = 0;
2559 // Transaction 2: a POST request. Reuses the socket kept alive from
2560 // transaction 1. The first attempts fails when writing the POST data.
2561 // This causes the transaction to retry with a new socket. The second
2562 // attempt succeeds.
2563 request[1].method = "POST";
2564 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422565 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512566 request[1].upload_data->AppendBytes("foo", 3);
2567 request[1].load_flags = 0;
2568
[email protected]228ff742009-06-05 01:19:592569 SessionDependencies session_deps;
2570 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512571
2572 // The first socket is used for transaction 1 and the first attempt of
2573 // transaction 2.
2574
2575 // The response of transaction 1.
2576 MockRead data_reads1[] = {
2577 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2578 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422579 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512580 };
2581 // The mock write results of transaction 1 and the first attempt of
2582 // transaction 2.
2583 MockWrite data_writes1[] = {
2584 MockWrite(false, 64), // GET
2585 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422586 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512587 };
[email protected]31a2bfe2010-02-09 08:03:392588 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2589 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512590
2591 // The second socket is used for the second attempt of transaction 2.
2592
2593 // The response of transaction 2.
2594 MockRead data_reads2[] = {
2595 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2596 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422597 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512598 };
2599 // The mock write results of the second attempt of transaction 2.
2600 MockWrite data_writes2[] = {
2601 MockWrite(false, 93), // POST
2602 MockWrite(false, 3), // POST data
2603 };
[email protected]31a2bfe2010-02-09 08:03:392604 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2605 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512606
[email protected]5ecc992a42009-11-11 01:41:592607 session_deps.socket_factory.AddSocketDataProvider(&data1);
2608 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512609
2610 const char* kExpectedResponseData[] = {
2611 "hello world", "welcome"
2612 };
2613
2614 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422615 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432616 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512617
2618 TestCompletionCallback callback;
2619
[email protected]5a1d7ca2010-04-28 20:12:272620 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422621 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512622
2623 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422624 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512625
[email protected]1c773ea12009-04-28 19:58:422626 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512627 EXPECT_TRUE(response != NULL);
2628
2629 EXPECT_TRUE(response->headers != NULL);
2630 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2631
2632 std::string response_data;
2633 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422634 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512635 EXPECT_EQ(kExpectedResponseData[i], response_data);
2636 }
2637}
[email protected]f9ee6b52008-11-08 06:46:232638
2639// Test the request-challenge-retry sequence for basic auth when there is
2640// an identity in the URL. The request should be sent as normal, but when
2641// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322642TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592643 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402644 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432645 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232646
[email protected]1c773ea12009-04-28 19:58:422647 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232648 request.method = "GET";
2649 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292650 request.url = GURL("http://foo:b@[email protected]/");
2651
2652 // The password contains an escaped character -- for this test to pass it
2653 // will need to be unescaped by HttpNetworkTransaction.
2654 EXPECT_EQ("b%40r", request.url.password());
2655
[email protected]ea9dc9a2009-09-05 00:43:322656 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232657
2658 MockWrite data_writes1[] = {
2659 MockWrite("GET / HTTP/1.1\r\n"
2660 "Host: www.google.com\r\n"
2661 "Connection: keep-alive\r\n\r\n"),
2662 };
2663
2664 MockRead data_reads1[] = {
2665 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2666 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2667 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422668 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232669 };
2670
2671 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322672 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232673 MockWrite data_writes2[] = {
2674 MockWrite("GET / HTTP/1.1\r\n"
2675 "Host: www.google.com\r\n"
2676 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292677 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232678 };
2679
2680 MockRead data_reads2[] = {
2681 MockRead("HTTP/1.0 200 OK\r\n"),
2682 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422683 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232684 };
2685
[email protected]31a2bfe2010-02-09 08:03:392686 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2687 data_writes1, arraysize(data_writes1));
2688 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2689 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592690 session_deps.socket_factory.AddSocketDataProvider(&data1);
2691 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232692
2693 TestCompletionCallback callback1;
2694
[email protected]5a1d7ca2010-04-28 20:12:272695 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422696 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232697
2698 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422699 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232700
[email protected]0757e7702009-03-27 04:00:222701 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2702 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442703 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422704 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222705 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422706 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222707 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2708
[email protected]1c773ea12009-04-28 19:58:422709 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232710 EXPECT_FALSE(response == NULL);
2711
2712 // There is no challenge info, since the identity in URL worked.
2713 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2714
2715 EXPECT_EQ(100, response->headers->GetContentLength());
2716
2717 // Empty the current queue.
2718 MessageLoop::current()->RunAllPending();
2719}
2720
[email protected]ea9dc9a2009-09-05 00:43:322721// Test the request-challenge-retry sequence for basic auth when there is
2722// an incorrect identity in the URL. The identity from the URL should be used
2723// only once.
2724TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2725 SessionDependencies session_deps;
2726 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432727 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322728
2729 HttpRequestInfo request;
2730 request.method = "GET";
2731 // Note: the URL has a username:password in it. The password "baz" is
2732 // wrong (should be "bar").
2733 request.url = GURL("http://foo:[email protected]/");
2734
2735 request.load_flags = LOAD_NORMAL;
2736
2737 MockWrite data_writes1[] = {
2738 MockWrite("GET / HTTP/1.1\r\n"
2739 "Host: www.google.com\r\n"
2740 "Connection: keep-alive\r\n\r\n"),
2741 };
2742
2743 MockRead data_reads1[] = {
2744 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2745 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2746 MockRead("Content-Length: 10\r\n\r\n"),
2747 MockRead(false, ERR_FAILED),
2748 };
2749
2750 // After the challenge above, the transaction will be restarted using the
2751 // identity from the url (foo, baz) to answer the challenge.
2752 MockWrite data_writes2[] = {
2753 MockWrite("GET / HTTP/1.1\r\n"
2754 "Host: www.google.com\r\n"
2755 "Connection: keep-alive\r\n"
2756 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2757 };
2758
2759 MockRead data_reads2[] = {
2760 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2761 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2762 MockRead("Content-Length: 10\r\n\r\n"),
2763 MockRead(false, ERR_FAILED),
2764 };
2765
2766 // After the challenge above, the transaction will be restarted using the
2767 // identity supplied by the user (foo, bar) to answer the challenge.
2768 MockWrite data_writes3[] = {
2769 MockWrite("GET / HTTP/1.1\r\n"
2770 "Host: www.google.com\r\n"
2771 "Connection: keep-alive\r\n"
2772 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2773 };
2774
2775 MockRead data_reads3[] = {
2776 MockRead("HTTP/1.0 200 OK\r\n"),
2777 MockRead("Content-Length: 100\r\n\r\n"),
2778 MockRead(false, OK),
2779 };
2780
[email protected]31a2bfe2010-02-09 08:03:392781 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2782 data_writes1, arraysize(data_writes1));
2783 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2784 data_writes2, arraysize(data_writes2));
2785 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2786 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592787 session_deps.socket_factory.AddSocketDataProvider(&data1);
2788 session_deps.socket_factory.AddSocketDataProvider(&data2);
2789 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322790
2791 TestCompletionCallback callback1;
2792
[email protected]5a1d7ca2010-04-28 20:12:272793 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322794 EXPECT_EQ(ERR_IO_PENDING, rv);
2795
2796 rv = callback1.WaitForResult();
2797 EXPECT_EQ(OK, rv);
2798
2799 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2800 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442801 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:322802 EXPECT_EQ(ERR_IO_PENDING, rv);
2803 rv = callback2.WaitForResult();
2804 EXPECT_EQ(OK, rv);
2805 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2806
2807 const HttpResponseInfo* response = trans->GetResponseInfo();
2808 EXPECT_FALSE(response == NULL);
2809 // The password prompt info should have been set in response->auth_challenge.
2810 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2811
2812 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2813 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2814 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2815
2816 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:442817 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:322818 EXPECT_EQ(ERR_IO_PENDING, rv);
2819 rv = callback3.WaitForResult();
2820 EXPECT_EQ(OK, rv);
2821 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2822
2823 response = trans->GetResponseInfo();
2824 EXPECT_FALSE(response == NULL);
2825
2826 // There is no challenge info, since the identity worked.
2827 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2828
2829 EXPECT_EQ(100, response->headers->GetContentLength());
2830
2831 // Empty the current queue.
2832 MessageLoop::current()->RunAllPending();
2833}
2834
[email protected]f9ee6b52008-11-08 06:46:232835// Test that previously tried username/passwords for a realm get re-used.
2836TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592837 SessionDependencies session_deps;
2838 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232839
2840 // Transaction 1: authenticate (foo, bar) on MyRealm1
2841 {
[email protected]5695b8c2009-09-30 21:36:432842 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232843
[email protected]1c773ea12009-04-28 19:58:422844 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232845 request.method = "GET";
2846 request.url = GURL("http://www.google.com/x/y/z");
2847 request.load_flags = 0;
2848
2849 MockWrite data_writes1[] = {
2850 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2851 "Host: www.google.com\r\n"
2852 "Connection: keep-alive\r\n\r\n"),
2853 };
2854
2855 MockRead data_reads1[] = {
2856 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2857 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2858 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422859 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232860 };
2861
2862 // Resend with authorization (username=foo, password=bar)
2863 MockWrite data_writes2[] = {
2864 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2865 "Host: www.google.com\r\n"
2866 "Connection: keep-alive\r\n"
2867 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2868 };
2869
2870 // Sever accepts the authorization.
2871 MockRead data_reads2[] = {
2872 MockRead("HTTP/1.0 200 OK\r\n"),
2873 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422874 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232875 };
2876
[email protected]31a2bfe2010-02-09 08:03:392877 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2878 data_writes1, arraysize(data_writes1));
2879 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2880 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592881 session_deps.socket_factory.AddSocketDataProvider(&data1);
2882 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232883
2884 TestCompletionCallback callback1;
2885
[email protected]5a1d7ca2010-04-28 20:12:272886 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422887 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232888
2889 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422890 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232891
[email protected]1c773ea12009-04-28 19:58:422892 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232893 EXPECT_FALSE(response == NULL);
2894
2895 // The password prompt info should have been set in
2896 // response->auth_challenge.
2897 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2898
[email protected]71e4573a2009-05-21 22:03:002899 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232900 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2901 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2902
2903 TestCompletionCallback callback2;
2904
[email protected]13c8a092010-07-29 06:15:442905 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422906 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232907
2908 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422909 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232910
2911 response = trans->GetResponseInfo();
2912 EXPECT_FALSE(response == NULL);
2913 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2914 EXPECT_EQ(100, response->headers->GetContentLength());
2915 }
2916
2917 // ------------------------------------------------------------------------
2918
2919 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2920 {
[email protected]5695b8c2009-09-30 21:36:432921 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232922
[email protected]1c773ea12009-04-28 19:58:422923 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232924 request.method = "GET";
2925 // Note that Transaction 1 was at /x/y/z, so this is in the same
2926 // protection space as MyRealm1.
2927 request.url = GURL("http://www.google.com/x/y/a/b");
2928 request.load_flags = 0;
2929
2930 MockWrite data_writes1[] = {
2931 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2932 "Host: www.google.com\r\n"
2933 "Connection: keep-alive\r\n"
2934 // Send preemptive authorization for MyRealm1
2935 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2936 };
2937
2938 // The server didn't like the preemptive authorization, and
2939 // challenges us for a different realm (MyRealm2).
2940 MockRead data_reads1[] = {
2941 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2942 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2943 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422944 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232945 };
2946
2947 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2948 MockWrite data_writes2[] = {
2949 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2950 "Host: www.google.com\r\n"
2951 "Connection: keep-alive\r\n"
2952 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2953 };
2954
2955 // Sever accepts the authorization.
2956 MockRead data_reads2[] = {
2957 MockRead("HTTP/1.0 200 OK\r\n"),
2958 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422959 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232960 };
2961
[email protected]31a2bfe2010-02-09 08:03:392962 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2963 data_writes1, arraysize(data_writes1));
2964 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2965 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592966 session_deps.socket_factory.AddSocketDataProvider(&data1);
2967 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232968
2969 TestCompletionCallback callback1;
2970
[email protected]5a1d7ca2010-04-28 20:12:272971 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422972 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232973
2974 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422975 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232976
[email protected]1c773ea12009-04-28 19:58:422977 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232978 EXPECT_FALSE(response == NULL);
2979
2980 // The password prompt info should have been set in
2981 // response->auth_challenge.
2982 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2983
[email protected]71e4573a2009-05-21 22:03:002984 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232985 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2986 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2987
2988 TestCompletionCallback callback2;
2989
[email protected]13c8a092010-07-29 06:15:442990 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:422991 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232992
2993 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422994 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232995
2996 response = trans->GetResponseInfo();
2997 EXPECT_FALSE(response == NULL);
2998 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2999 EXPECT_EQ(100, response->headers->GetContentLength());
3000 }
3001
3002 // ------------------------------------------------------------------------
3003
3004 // Transaction 3: Resend a request in MyRealm's protection space --
3005 // succeed with preemptive authorization.
3006 {
[email protected]5695b8c2009-09-30 21:36:433007 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233008
[email protected]1c773ea12009-04-28 19:58:423009 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233010 request.method = "GET";
3011 request.url = GURL("http://www.google.com/x/y/z2");
3012 request.load_flags = 0;
3013
3014 MockWrite data_writes1[] = {
3015 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3016 "Host: www.google.com\r\n"
3017 "Connection: keep-alive\r\n"
3018 // The authorization for MyRealm1 gets sent preemptively
3019 // (since the url is in the same protection space)
3020 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3021 };
3022
3023 // Sever accepts the preemptive authorization
3024 MockRead data_reads1[] = {
3025 MockRead("HTTP/1.0 200 OK\r\n"),
3026 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423027 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233028 };
3029
[email protected]31a2bfe2010-02-09 08:03:393030 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3031 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593032 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233033
3034 TestCompletionCallback callback1;
3035
[email protected]5a1d7ca2010-04-28 20:12:273036 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423037 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233038
3039 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423040 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233041
[email protected]1c773ea12009-04-28 19:58:423042 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233043 EXPECT_FALSE(response == NULL);
3044
3045 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3046 EXPECT_EQ(100, response->headers->GetContentLength());
3047 }
3048
3049 // ------------------------------------------------------------------------
3050
3051 // Transaction 4: request another URL in MyRealm (however the
3052 // url is not known to belong to the protection space, so no pre-auth).
3053 {
[email protected]5695b8c2009-09-30 21:36:433054 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233055
[email protected]1c773ea12009-04-28 19:58:423056 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233057 request.method = "GET";
3058 request.url = GURL("http://www.google.com/x/1");
3059 request.load_flags = 0;
3060
3061 MockWrite data_writes1[] = {
3062 MockWrite("GET /x/1 HTTP/1.1\r\n"
3063 "Host: www.google.com\r\n"
3064 "Connection: keep-alive\r\n\r\n"),
3065 };
3066
3067 MockRead data_reads1[] = {
3068 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3069 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3070 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423071 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233072 };
3073
3074 // Resend with authorization from MyRealm's cache.
3075 MockWrite data_writes2[] = {
3076 MockWrite("GET /x/1 HTTP/1.1\r\n"
3077 "Host: www.google.com\r\n"
3078 "Connection: keep-alive\r\n"
3079 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3080 };
3081
3082 // Sever accepts the authorization.
3083 MockRead data_reads2[] = {
3084 MockRead("HTTP/1.0 200 OK\r\n"),
3085 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423086 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233087 };
3088
[email protected]31a2bfe2010-02-09 08:03:393089 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3090 data_writes1, arraysize(data_writes1));
3091 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3092 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593093 session_deps.socket_factory.AddSocketDataProvider(&data1);
3094 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233095
3096 TestCompletionCallback callback1;
3097
[email protected]5a1d7ca2010-04-28 20:12:273098 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423099 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233100
3101 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423102 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233103
[email protected]0757e7702009-03-27 04:00:223104 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3105 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443106 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423107 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223108 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423109 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223110 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3111
[email protected]1c773ea12009-04-28 19:58:423112 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233113 EXPECT_FALSE(response == NULL);
3114 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3115 EXPECT_EQ(100, response->headers->GetContentLength());
3116 }
3117
3118 // ------------------------------------------------------------------------
3119
3120 // Transaction 5: request a URL in MyRealm, but the server rejects the
3121 // cached identity. Should invalidate and re-prompt.
3122 {
[email protected]5695b8c2009-09-30 21:36:433123 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233124
[email protected]1c773ea12009-04-28 19:58:423125 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233126 request.method = "GET";
3127 request.url = GURL("http://www.google.com/p/q/t");
3128 request.load_flags = 0;
3129
3130 MockWrite data_writes1[] = {
3131 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3132 "Host: www.google.com\r\n"
3133 "Connection: keep-alive\r\n\r\n"),
3134 };
3135
3136 MockRead data_reads1[] = {
3137 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3138 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3139 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423140 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233141 };
3142
3143 // Resend with authorization from cache for MyRealm.
3144 MockWrite data_writes2[] = {
3145 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3146 "Host: www.google.com\r\n"
3147 "Connection: keep-alive\r\n"
3148 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3149 };
3150
3151 // Sever rejects the authorization.
3152 MockRead data_reads2[] = {
3153 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3154 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3155 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423156 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233157 };
3158
3159 // At this point we should prompt for new credentials for MyRealm.
3160 // Restart with username=foo3, password=foo4.
3161 MockWrite data_writes3[] = {
3162 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3163 "Host: www.google.com\r\n"
3164 "Connection: keep-alive\r\n"
3165 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3166 };
3167
3168 // Sever accepts the authorization.
3169 MockRead data_reads3[] = {
3170 MockRead("HTTP/1.0 200 OK\r\n"),
3171 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423172 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233173 };
3174
[email protected]31a2bfe2010-02-09 08:03:393175 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3176 data_writes1, arraysize(data_writes1));
3177 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3178 data_writes2, arraysize(data_writes2));
3179 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3180 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593181 session_deps.socket_factory.AddSocketDataProvider(&data1);
3182 session_deps.socket_factory.AddSocketDataProvider(&data2);
3183 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233184
3185 TestCompletionCallback callback1;
3186
[email protected]5a1d7ca2010-04-28 20:12:273187 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423188 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233189
3190 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423191 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233192
[email protected]0757e7702009-03-27 04:00:223193 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3194 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443195 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423196 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223197 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423198 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223199 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3200
[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
[email protected]0757e7702009-03-27 04:00:223212 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233213
[email protected]13c8a092010-07-29 06:15:443214 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423215 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233216
[email protected]0757e7702009-03-27 04:00:223217 rv = callback3.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}
[email protected]89ceba9a2009-03-21 03:46:063226
[email protected]3c32c5f2010-05-18 15:18:123227// Tests that nonce count increments when multiple auth attempts
3228// are started with the same nonce.
3229TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3230 SessionDependencies session_deps;
3231 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3232 HttpAuthHandlerDigest::SetFixedCnonce(true);
3233
3234 // Transaction 1: authenticate (foo, bar) on MyRealm1
3235 {
3236 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3237
3238 HttpRequestInfo request;
3239 request.method = "GET";
3240 request.url = GURL("http://www.google.com/x/y/z");
3241 request.load_flags = 0;
3242
3243 MockWrite data_writes1[] = {
3244 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3245 "Host: www.google.com\r\n"
3246 "Connection: keep-alive\r\n\r\n"),
3247 };
3248
3249 MockRead data_reads1[] = {
3250 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3251 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3252 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3253 MockRead(false, OK),
3254 };
3255
3256 // Resend with authorization (username=foo, password=bar)
3257 MockWrite data_writes2[] = {
3258 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3259 "Host: www.google.com\r\n"
3260 "Connection: keep-alive\r\n"
3261 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3262 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3263 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3264 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3265 };
3266
3267 // Sever accepts the authorization.
3268 MockRead data_reads2[] = {
3269 MockRead("HTTP/1.0 200 OK\r\n"),
3270 MockRead(false, OK),
3271 };
3272
3273 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3274 data_writes1, arraysize(data_writes1));
3275 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3276 data_writes2, arraysize(data_writes2));
3277 session_deps.socket_factory.AddSocketDataProvider(&data1);
3278 session_deps.socket_factory.AddSocketDataProvider(&data2);
3279
3280 TestCompletionCallback callback1;
3281
3282 int rv = trans->Start(&request, &callback1, BoundNetLog());
3283 EXPECT_EQ(ERR_IO_PENDING, rv);
3284
3285 rv = callback1.WaitForResult();
3286 EXPECT_EQ(OK, rv);
3287
3288 const HttpResponseInfo* response = trans->GetResponseInfo();
3289 ASSERT_FALSE(response == NULL);
3290
3291 // The password prompt info should have been set in
3292 // response->auth_challenge.
3293 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3294
3295 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3296 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3297 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3298
3299 TestCompletionCallback callback2;
3300
[email protected]13c8a092010-07-29 06:15:443301 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123302 EXPECT_EQ(ERR_IO_PENDING, rv);
3303
3304 rv = callback2.WaitForResult();
3305 EXPECT_EQ(OK, rv);
3306
3307 response = trans->GetResponseInfo();
3308 ASSERT_FALSE(response == NULL);
3309 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3310 }
3311
3312 // ------------------------------------------------------------------------
3313
3314 // Transaction 2: Request another resource in digestive's protection space.
3315 // This will preemptively add an Authorization header which should have an
3316 // "nc" value of 2 (as compared to 1 in the first use.
3317 {
3318 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3319
3320 HttpRequestInfo request;
3321 request.method = "GET";
3322 // Note that Transaction 1 was at /x/y/z, so this is in the same
3323 // protection space as digest.
3324 request.url = GURL("http://www.google.com/x/y/a/b");
3325 request.load_flags = 0;
3326
3327 MockWrite data_writes1[] = {
3328 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3329 "Host: www.google.com\r\n"
3330 "Connection: keep-alive\r\n"
3331 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3332 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3333 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3334 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3335 };
3336
3337 // Sever accepts the authorization.
3338 MockRead data_reads1[] = {
3339 MockRead("HTTP/1.0 200 OK\r\n"),
3340 MockRead("Content-Length: 100\r\n\r\n"),
3341 MockRead(false, OK),
3342 };
3343
3344 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3345 data_writes1, arraysize(data_writes1));
3346 session_deps.socket_factory.AddSocketDataProvider(&data1);
3347
3348 TestCompletionCallback callback1;
3349
3350 int rv = trans->Start(&request, &callback1, BoundNetLog());
3351 EXPECT_EQ(ERR_IO_PENDING, rv);
3352
3353 rv = callback1.WaitForResult();
3354 EXPECT_EQ(OK, rv);
3355
3356 const HttpResponseInfo* response = trans->GetResponseInfo();
3357 ASSERT_FALSE(response == NULL);
3358 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3359 }
3360}
3361
[email protected]89ceba9a2009-03-21 03:46:063362// Test the ResetStateForRestart() private method.
3363TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3364 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593365 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403366 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433367 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063368
3369 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063370 trans->read_buf_ = new IOBuffer(15);
3371 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573372 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063373
3374 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143375 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573376 response->auth_challenge = new AuthChallengeInfo();
3377 response->ssl_info.cert_status = -15;
3378 response->response_time = base::Time::Now();
3379 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063380
3381 { // Setup state for response_.vary_data
3382 HttpRequestInfo request;
3383 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3384 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573385 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433386 request.extra_headers.SetHeader("Foo", "1");
3387 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573388 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063389 }
3390
3391 // Cause the above state to be reset.
3392 trans->ResetStateForRestart();
3393
3394 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073395 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063396 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573397 EXPECT_EQ(0U, trans->request_headers_.size());
3398 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3399 EXPECT_TRUE(response->headers.get() == NULL);
3400 EXPECT_EQ(false, response->was_cached);
3401 EXPECT_EQ(0, response->ssl_info.cert_status);
3402 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063403}
3404
[email protected]bacff652009-03-31 17:50:333405// Test HTTPS connections to a site with a bad certificate
3406TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593407 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403408 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433409 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333410
3411 HttpRequestInfo request;
3412 request.method = "GET";
3413 request.url = GURL("https://www.google.com/");
3414 request.load_flags = 0;
3415
3416 MockWrite data_writes[] = {
3417 MockWrite("GET / HTTP/1.1\r\n"
3418 "Host: www.google.com\r\n"
3419 "Connection: keep-alive\r\n\r\n"),
3420 };
3421
3422 MockRead data_reads[] = {
3423 MockRead("HTTP/1.0 200 OK\r\n"),
3424 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3425 MockRead("Content-Length: 100\r\n\r\n"),
3426 MockRead(false, OK),
3427 };
3428
[email protected]5ecc992a42009-11-11 01:41:593429 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393430 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3431 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593432 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3433 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333434
[email protected]5ecc992a42009-11-11 01:41:593435 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3436 session_deps.socket_factory.AddSocketDataProvider(&data);
3437 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3438 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333439
3440 TestCompletionCallback callback;
3441
[email protected]5a1d7ca2010-04-28 20:12:273442 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333443 EXPECT_EQ(ERR_IO_PENDING, rv);
3444
3445 rv = callback.WaitForResult();
3446 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3447
3448 rv = trans->RestartIgnoringLastError(&callback);
3449 EXPECT_EQ(ERR_IO_PENDING, rv);
3450
3451 rv = callback.WaitForResult();
3452 EXPECT_EQ(OK, rv);
3453
3454 const HttpResponseInfo* response = trans->GetResponseInfo();
3455
3456 EXPECT_FALSE(response == NULL);
3457 EXPECT_EQ(100, response->headers->GetContentLength());
3458}
3459
3460// Test HTTPS connections to a site with a bad certificate, going through a
3461// proxy
3462TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593463 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333464
3465 HttpRequestInfo request;
3466 request.method = "GET";
3467 request.url = GURL("https://www.google.com/");
3468 request.load_flags = 0;
3469
3470 MockWrite proxy_writes[] = {
3471 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453472 "Host: www.google.com\r\n"
3473 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333474 };
3475
3476 MockRead proxy_reads[] = {
3477 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423478 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333479 };
3480
3481 MockWrite data_writes[] = {
3482 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453483 "Host: www.google.com\r\n"
3484 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333485 MockWrite("GET / HTTP/1.1\r\n"
3486 "Host: www.google.com\r\n"
3487 "Connection: keep-alive\r\n\r\n"),
3488 };
3489
3490 MockRead data_reads[] = {
3491 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3492 MockRead("HTTP/1.0 200 OK\r\n"),
3493 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3494 MockRead("Content-Length: 100\r\n\r\n"),
3495 MockRead(false, OK),
3496 };
3497
[email protected]31a2bfe2010-02-09 08:03:393498 StaticSocketDataProvider ssl_bad_certificate(
3499 proxy_reads, arraysize(proxy_reads),
3500 proxy_writes, arraysize(proxy_writes));
3501 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3502 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593503 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3504 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333505
[email protected]5ecc992a42009-11-11 01:41:593506 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3507 session_deps.socket_factory.AddSocketDataProvider(&data);
3508 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3509 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333510
3511 TestCompletionCallback callback;
3512
3513 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593514 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333515
[email protected]d207a5f2009-06-04 05:28:403516 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433517 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333518
[email protected]5a1d7ca2010-04-28 20:12:273519 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333520 EXPECT_EQ(ERR_IO_PENDING, rv);
3521
3522 rv = callback.WaitForResult();
3523 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3524
3525 rv = trans->RestartIgnoringLastError(&callback);
3526 EXPECT_EQ(ERR_IO_PENDING, rv);
3527
3528 rv = callback.WaitForResult();
3529 EXPECT_EQ(OK, rv);
3530
3531 const HttpResponseInfo* response = trans->GetResponseInfo();
3532
3533 EXPECT_FALSE(response == NULL);
3534 EXPECT_EQ(100, response->headers->GetContentLength());
3535 }
3536}
3537
[email protected]1c773ea12009-04-28 19:58:423538TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593539 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403540 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433541 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423542
3543 HttpRequestInfo request;
3544 request.method = "GET";
3545 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433546 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3547 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423548
3549 MockWrite data_writes[] = {
3550 MockWrite("GET / HTTP/1.1\r\n"
3551 "Host: www.google.com\r\n"
3552 "Connection: keep-alive\r\n"
3553 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3554 };
3555
3556 // Lastly, the server responds with the actual content.
3557 MockRead data_reads[] = {
3558 MockRead("HTTP/1.0 200 OK\r\n"),
3559 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3560 MockRead("Content-Length: 100\r\n\r\n"),
3561 MockRead(false, OK),
3562 };
3563
[email protected]31a2bfe2010-02-09 08:03:393564 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3565 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593566 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423567
3568 TestCompletionCallback callback;
3569
[email protected]5a1d7ca2010-04-28 20:12:273570 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423571 EXPECT_EQ(ERR_IO_PENDING, rv);
3572
3573 rv = callback.WaitForResult();
3574 EXPECT_EQ(OK, rv);
3575}
3576
3577TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593578 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403579 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433580 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423581
3582 HttpRequestInfo request;
3583 request.method = "GET";
3584 request.url = GURL("http://www.google.com/");
3585 request.load_flags = 0;
3586 request.referrer = GURL("http://the.previous.site.com/");
3587
3588 MockWrite data_writes[] = {
3589 MockWrite("GET / HTTP/1.1\r\n"
3590 "Host: www.google.com\r\n"
3591 "Connection: keep-alive\r\n"
3592 "Referer: http://the.previous.site.com/\r\n\r\n"),
3593 };
3594
3595 // Lastly, the server responds with the actual content.
3596 MockRead data_reads[] = {
3597 MockRead("HTTP/1.0 200 OK\r\n"),
3598 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3599 MockRead("Content-Length: 100\r\n\r\n"),
3600 MockRead(false, OK),
3601 };
3602
[email protected]31a2bfe2010-02-09 08:03:393603 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3604 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593605 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423606
3607 TestCompletionCallback callback;
3608
[email protected]5a1d7ca2010-04-28 20:12:273609 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423610 EXPECT_EQ(ERR_IO_PENDING, rv);
3611
3612 rv = callback.WaitForResult();
3613 EXPECT_EQ(OK, rv);
3614}
3615
3616TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593617 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403618 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433619 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423620
3621 HttpRequestInfo request;
3622 request.method = "POST";
3623 request.url = GURL("http://www.google.com/");
3624
3625 MockWrite data_writes[] = {
3626 MockWrite("POST / HTTP/1.1\r\n"
3627 "Host: www.google.com\r\n"
3628 "Connection: keep-alive\r\n"
3629 "Content-Length: 0\r\n\r\n"),
3630 };
3631
3632 // Lastly, the server responds with the actual content.
3633 MockRead data_reads[] = {
3634 MockRead("HTTP/1.0 200 OK\r\n"),
3635 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3636 MockRead("Content-Length: 100\r\n\r\n"),
3637 MockRead(false, OK),
3638 };
3639
[email protected]31a2bfe2010-02-09 08:03:393640 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3641 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593642 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423643
3644 TestCompletionCallback callback;
3645
[email protected]5a1d7ca2010-04-28 20:12:273646 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423647 EXPECT_EQ(ERR_IO_PENDING, rv);
3648
3649 rv = callback.WaitForResult();
3650 EXPECT_EQ(OK, rv);
3651}
3652
3653TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593654 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403655 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433656 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423657
3658 HttpRequestInfo request;
3659 request.method = "PUT";
3660 request.url = GURL("http://www.google.com/");
3661
3662 MockWrite data_writes[] = {
3663 MockWrite("PUT / HTTP/1.1\r\n"
3664 "Host: www.google.com\r\n"
3665 "Connection: keep-alive\r\n"
3666 "Content-Length: 0\r\n\r\n"),
3667 };
3668
3669 // Lastly, the server responds with the actual content.
3670 MockRead data_reads[] = {
3671 MockRead("HTTP/1.0 200 OK\r\n"),
3672 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3673 MockRead("Content-Length: 100\r\n\r\n"),
3674 MockRead(false, OK),
3675 };
3676
[email protected]31a2bfe2010-02-09 08:03:393677 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3678 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593679 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423680
3681 TestCompletionCallback callback;
3682
[email protected]5a1d7ca2010-04-28 20:12:273683 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423684 EXPECT_EQ(ERR_IO_PENDING, rv);
3685
3686 rv = callback.WaitForResult();
3687 EXPECT_EQ(OK, rv);
3688}
3689
3690TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593691 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403692 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433693 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423694
3695 HttpRequestInfo request;
3696 request.method = "HEAD";
3697 request.url = GURL("http://www.google.com/");
3698
3699 MockWrite data_writes[] = {
3700 MockWrite("HEAD / HTTP/1.1\r\n"
3701 "Host: www.google.com\r\n"
3702 "Connection: keep-alive\r\n"
3703 "Content-Length: 0\r\n\r\n"),
3704 };
3705
3706 // Lastly, the server responds with the actual content.
3707 MockRead data_reads[] = {
3708 MockRead("HTTP/1.0 200 OK\r\n"),
3709 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3710 MockRead("Content-Length: 100\r\n\r\n"),
3711 MockRead(false, OK),
3712 };
3713
[email protected]31a2bfe2010-02-09 08:03:393714 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3715 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593716 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423717
3718 TestCompletionCallback callback;
3719
[email protected]5a1d7ca2010-04-28 20:12:273720 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423721 EXPECT_EQ(ERR_IO_PENDING, rv);
3722
3723 rv = callback.WaitForResult();
3724 EXPECT_EQ(OK, rv);
3725}
3726
3727TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593728 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403729 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433730 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423731
3732 HttpRequestInfo request;
3733 request.method = "GET";
3734 request.url = GURL("http://www.google.com/");
3735 request.load_flags = LOAD_BYPASS_CACHE;
3736
3737 MockWrite data_writes[] = {
3738 MockWrite("GET / HTTP/1.1\r\n"
3739 "Host: www.google.com\r\n"
3740 "Connection: keep-alive\r\n"
3741 "Pragma: no-cache\r\n"
3742 "Cache-Control: no-cache\r\n\r\n"),
3743 };
3744
3745 // Lastly, the server responds with the actual content.
3746 MockRead data_reads[] = {
3747 MockRead("HTTP/1.0 200 OK\r\n"),
3748 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3749 MockRead("Content-Length: 100\r\n\r\n"),
3750 MockRead(false, OK),
3751 };
3752
[email protected]31a2bfe2010-02-09 08:03:393753 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3754 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593755 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423756
3757 TestCompletionCallback callback;
3758
[email protected]5a1d7ca2010-04-28 20:12:273759 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423760 EXPECT_EQ(ERR_IO_PENDING, rv);
3761
3762 rv = callback.WaitForResult();
3763 EXPECT_EQ(OK, rv);
3764}
3765
3766TEST_F(HttpNetworkTransactionTest,
3767 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593768 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403769 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433770 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423771
3772 HttpRequestInfo request;
3773 request.method = "GET";
3774 request.url = GURL("http://www.google.com/");
3775 request.load_flags = LOAD_VALIDATE_CACHE;
3776
3777 MockWrite data_writes[] = {
3778 MockWrite("GET / HTTP/1.1\r\n"
3779 "Host: www.google.com\r\n"
3780 "Connection: keep-alive\r\n"
3781 "Cache-Control: max-age=0\r\n\r\n"),
3782 };
3783
3784 // Lastly, the server responds with the actual content.
3785 MockRead data_reads[] = {
3786 MockRead("HTTP/1.0 200 OK\r\n"),
3787 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3788 MockRead("Content-Length: 100\r\n\r\n"),
3789 MockRead(false, OK),
3790 };
3791
[email protected]31a2bfe2010-02-09 08:03:393792 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3793 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593794 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423795
3796 TestCompletionCallback callback;
3797
[email protected]5a1d7ca2010-04-28 20:12:273798 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423799 EXPECT_EQ(ERR_IO_PENDING, rv);
3800
3801 rv = callback.WaitForResult();
3802 EXPECT_EQ(OK, rv);
3803}
3804
3805TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593806 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403807 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433808 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423809
3810 HttpRequestInfo request;
3811 request.method = "GET";
3812 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433813 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423814
3815 MockWrite data_writes[] = {
3816 MockWrite("GET / HTTP/1.1\r\n"
3817 "Host: www.google.com\r\n"
3818 "Connection: keep-alive\r\n"
3819 "FooHeader: Bar\r\n\r\n"),
3820 };
3821
3822 // Lastly, the server responds with the actual content.
3823 MockRead data_reads[] = {
3824 MockRead("HTTP/1.0 200 OK\r\n"),
3825 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3826 MockRead("Content-Length: 100\r\n\r\n"),
3827 MockRead(false, OK),
3828 };
3829
[email protected]31a2bfe2010-02-09 08:03:393830 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3831 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593832 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423833
3834 TestCompletionCallback callback;
3835
[email protected]5a1d7ca2010-04-28 20:12:273836 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423837 EXPECT_EQ(ERR_IO_PENDING, rv);
3838
3839 rv = callback.WaitForResult();
3840 EXPECT_EQ(OK, rv);
3841}
3842
[email protected]270c6412010-03-29 22:02:473843TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3844 SessionDependencies session_deps;
3845 scoped_ptr<HttpTransaction> trans(
3846 new HttpNetworkTransaction(CreateSession(&session_deps)));
3847
3848 HttpRequestInfo request;
3849 request.method = "GET";
3850 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433851 request.extra_headers.SetHeader("referer", "www.foo.com");
3852 request.extra_headers.SetHeader("hEllo", "Kitty");
3853 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473854
3855 MockWrite data_writes[] = {
3856 MockWrite("GET / HTTP/1.1\r\n"
3857 "Host: www.google.com\r\n"
3858 "Connection: keep-alive\r\n"
3859 "hEllo: Kitty\r\n"
3860 "FoO: bar\r\n\r\n"),
3861 };
3862
3863 // Lastly, the server responds with the actual content.
3864 MockRead data_reads[] = {
3865 MockRead("HTTP/1.0 200 OK\r\n"),
3866 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3867 MockRead("Content-Length: 100\r\n\r\n"),
3868 MockRead(false, OK),
3869 };
3870
3871 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3872 data_writes, arraysize(data_writes));
3873 session_deps.socket_factory.AddSocketDataProvider(&data);
3874
3875 TestCompletionCallback callback;
3876
[email protected]5a1d7ca2010-04-28 20:12:273877 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473878 EXPECT_EQ(ERR_IO_PENDING, rv);
3879
3880 rv = callback.WaitForResult();
3881 EXPECT_EQ(OK, rv);
3882}
3883
[email protected]3cd17242009-06-23 02:59:023884TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093885 SessionDependencies session_deps(
3886 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023887
3888 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433889 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023890
3891 HttpRequestInfo request;
3892 request.method = "GET";
3893 request.url = GURL("http://www.google.com/");
3894 request.load_flags = 0;
3895
3896 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3897 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3898
3899 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353900 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023901 MockWrite("GET / HTTP/1.1\r\n"
3902 "Host: www.google.com\r\n"
3903 "Connection: keep-alive\r\n\r\n")
3904 };
3905
3906 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593907 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023908 MockRead("HTTP/1.0 200 OK\r\n"),
3909 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3910 MockRead("Payload"),
3911 MockRead(false, OK)
3912 };
3913
[email protected]31a2bfe2010-02-09 08:03:393914 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3915 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593916 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023917
3918 TestCompletionCallback callback;
3919
[email protected]5a1d7ca2010-04-28 20:12:273920 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023921 EXPECT_EQ(ERR_IO_PENDING, rv);
3922
3923 rv = callback.WaitForResult();
3924 EXPECT_EQ(OK, rv);
3925
3926 const HttpResponseInfo* response = trans->GetResponseInfo();
3927 EXPECT_FALSE(response == NULL);
3928
3929 std::string response_text;
3930 rv = ReadTransaction(trans.get(), &response_text);
3931 EXPECT_EQ(OK, rv);
3932 EXPECT_EQ("Payload", response_text);
3933}
3934
3935TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093936 SessionDependencies session_deps(
3937 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023938
3939 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433940 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023941
3942 HttpRequestInfo request;
3943 request.method = "GET";
3944 request.url = GURL("https://www.google.com/");
3945 request.load_flags = 0;
3946
3947 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3948 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3949
3950 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353951 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3952 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023953 MockWrite("GET / HTTP/1.1\r\n"
3954 "Host: www.google.com\r\n"
3955 "Connection: keep-alive\r\n\r\n")
3956 };
3957
3958 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353959 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3960 arraysize(read_buffer)),
3961 MockRead("HTTP/1.0 200 OK\r\n"),
3962 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3963 MockRead("Payload"),
3964 MockRead(false, OK)
3965 };
3966
[email protected]31a2bfe2010-02-09 08:03:393967 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3968 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593969 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353970
[email protected]5ecc992a42009-11-11 01:41:593971 SSLSocketDataProvider ssl(true, OK);
3972 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353973
3974 TestCompletionCallback callback;
3975
[email protected]5a1d7ca2010-04-28 20:12:273976 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353977 EXPECT_EQ(ERR_IO_PENDING, rv);
3978
3979 rv = callback.WaitForResult();
3980 EXPECT_EQ(OK, rv);
3981
3982 const HttpResponseInfo* response = trans->GetResponseInfo();
3983 EXPECT_FALSE(response == NULL);
3984
3985 std::string response_text;
3986 rv = ReadTransaction(trans.get(), &response_text);
3987 EXPECT_EQ(OK, rv);
3988 EXPECT_EQ("Payload", response_text);
3989}
3990
3991TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093992 SessionDependencies session_deps(
3993 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353994
3995 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433996 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353997
3998 HttpRequestInfo request;
3999 request.method = "GET";
4000 request.url = GURL("http://www.google.com/");
4001 request.load_flags = 0;
4002
4003 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4004 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374005 const char kSOCKS5OkRequest[] = {
4006 0x05, // Version
4007 0x01, // Command (CONNECT)
4008 0x00, // Reserved.
4009 0x03, // Address type (DOMAINNAME).
4010 0x0E, // Length of domain (14)
4011 // Domain string:
4012 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4013 0x00, 0x50, // 16-bit port (80)
4014 };
[email protected]e0c27be2009-07-15 13:09:354015 const char kSOCKS5OkResponse[] =
4016 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4017
4018 MockWrite data_writes[] = {
4019 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4020 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4021 MockWrite("GET / HTTP/1.1\r\n"
4022 "Host: www.google.com\r\n"
4023 "Connection: keep-alive\r\n\r\n")
4024 };
4025
4026 MockRead data_reads[] = {
4027 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4028 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4029 MockRead("HTTP/1.0 200 OK\r\n"),
4030 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4031 MockRead("Payload"),
4032 MockRead(false, OK)
4033 };
4034
[email protected]31a2bfe2010-02-09 08:03:394035 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4036 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594037 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354038
4039 TestCompletionCallback callback;
4040
[email protected]5a1d7ca2010-04-28 20:12:274041 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354042 EXPECT_EQ(ERR_IO_PENDING, rv);
4043
4044 rv = callback.WaitForResult();
4045 EXPECT_EQ(OK, rv);
4046
4047 const HttpResponseInfo* response = trans->GetResponseInfo();
4048 EXPECT_FALSE(response == NULL);
4049
4050 std::string response_text;
4051 rv = ReadTransaction(trans.get(), &response_text);
4052 EXPECT_EQ(OK, rv);
4053 EXPECT_EQ("Payload", response_text);
4054}
4055
4056TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094057 SessionDependencies session_deps(
4058 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354059
4060 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434061 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354062
4063 HttpRequestInfo request;
4064 request.method = "GET";
4065 request.url = GURL("https://www.google.com/");
4066 request.load_flags = 0;
4067
4068 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4069 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374070 const unsigned char kSOCKS5OkRequest[] = {
4071 0x05, // Version
4072 0x01, // Command (CONNECT)
4073 0x00, // Reserved.
4074 0x03, // Address type (DOMAINNAME).
4075 0x0E, // Length of domain (14)
4076 // Domain string:
4077 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4078 0x01, 0xBB, // 16-bit port (443)
4079 };
4080
[email protected]e0c27be2009-07-15 13:09:354081 const char kSOCKS5OkResponse[] =
4082 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4083
4084 MockWrite data_writes[] = {
4085 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4086 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4087 arraysize(kSOCKS5OkRequest)),
4088 MockWrite("GET / HTTP/1.1\r\n"
4089 "Host: www.google.com\r\n"
4090 "Connection: keep-alive\r\n\r\n")
4091 };
4092
4093 MockRead data_reads[] = {
4094 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4095 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024096 MockRead("HTTP/1.0 200 OK\r\n"),
4097 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4098 MockRead("Payload"),
4099 MockRead(false, OK)
4100 };
4101
[email protected]31a2bfe2010-02-09 08:03:394102 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4103 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594104 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024105
[email protected]5ecc992a42009-11-11 01:41:594106 SSLSocketDataProvider ssl(true, OK);
4107 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024108
4109 TestCompletionCallback callback;
4110
[email protected]5a1d7ca2010-04-28 20:12:274111 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024112 EXPECT_EQ(ERR_IO_PENDING, rv);
4113
4114 rv = callback.WaitForResult();
4115 EXPECT_EQ(OK, rv);
4116
4117 const HttpResponseInfo* response = trans->GetResponseInfo();
4118 EXPECT_FALSE(response == NULL);
4119
4120 std::string response_text;
4121 rv = ReadTransaction(trans.get(), &response_text);
4122 EXPECT_EQ(OK, rv);
4123 EXPECT_EQ("Payload", response_text);
4124}
4125
[email protected]04e5be32009-06-26 20:00:314126// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064127
4128struct GroupNameTest {
4129 std::string proxy_server;
4130 std::string url;
4131 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184132 bool ssl;
[email protected]2d731a32010-04-29 01:04:064133};
4134
4135scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4136 const std::string& proxy_server) {
4137 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4138 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4139
4140 HttpAlternateProtocols* alternate_protocols =
4141 session->mutable_alternate_protocols();
4142 alternate_protocols->SetAlternateProtocolFor(
4143 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354144 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064145
4146 return session;
4147}
4148
4149int GroupNameTransactionHelper(
4150 const std::string& url,
4151 const scoped_refptr<HttpNetworkSession>& session) {
4152 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4153
4154 HttpRequestInfo request;
4155 request.method = "GET";
4156 request.url = GURL(url);
4157 request.load_flags = 0;
4158
4159 TestCompletionCallback callback;
4160
4161 // We do not complete this request, the dtor will clean the transaction up.
4162 return trans->Start(&request, &callback, BoundNetLog());
4163}
4164
4165TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4166 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314167 {
[email protected]2d731a32010-04-29 01:04:064168 "", // unused
[email protected]04e5be32009-06-26 20:00:314169 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544170 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184171 false,
[email protected]2ff8b312010-04-26 22:20:544172 },
4173 {
[email protected]2d731a32010-04-29 01:04:064174 "", // unused
[email protected]2ff8b312010-04-26 22:20:544175 "http://[2001:1418:13:1::25]/direct",
4176 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184177 false,
[email protected]04e5be32009-06-26 20:00:314178 },
[email protected]04e5be32009-06-26 20:00:314179
4180 // SSL Tests
4181 {
[email protected]2d731a32010-04-29 01:04:064182 "", // unused
[email protected]04e5be32009-06-26 20:00:314183 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024184 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184185 true,
[email protected]04e5be32009-06-26 20:00:314186 },
4187 {
[email protected]2d731a32010-04-29 01:04:064188 "", // unused
4189 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024190 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184191 true,
[email protected]04e5be32009-06-26 20:00:314192 },
4193 {
[email protected]2d731a32010-04-29 01:04:064194 "", // unused
[email protected]2ff8b312010-04-26 22:20:544195 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024196 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184197 true,
[email protected]2ff8b312010-04-26 22:20:544198 },
[email protected]2d731a32010-04-29 01:04:064199 };
[email protected]2ff8b312010-04-26 22:20:544200
[email protected]2d731a32010-04-29 01:04:064201 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4202
4203 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4204 scoped_refptr<HttpNetworkSession> session(
4205 SetupSessionForGroupNameTests(tests[i].proxy_server));
4206
4207 HttpNetworkSessionPeer peer(session);
4208 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4209 new CaptureGroupNameTCPSocketPool(session.get()));
4210 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184211 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4212 new CaptureGroupNameSSLSocketPool(session.get()));
4213 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064214
4215 EXPECT_EQ(ERR_IO_PENDING,
4216 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184217 if (tests[i].ssl)
4218 EXPECT_EQ(tests[i].expected_group_name,
4219 ssl_conn_pool->last_group_name_received());
4220 else
4221 EXPECT_EQ(tests[i].expected_group_name,
4222 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064223 }
4224
4225 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4226}
4227
4228TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4229 const GroupNameTest tests[] = {
4230 {
4231 "http_proxy",
4232 "http://www.google.com/http_proxy_normal",
4233 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184234 false,
[email protected]2d731a32010-04-29 01:04:064235 },
4236
4237 // SSL Tests
4238 {
4239 "http_proxy",
4240 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024241 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184242 true,
[email protected]2d731a32010-04-29 01:04:064243 },
4244
[email protected]9faeded92010-04-29 20:03:054245 {
4246 "http_proxy",
4247 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024248 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184249 true,
[email protected]9faeded92010-04-29 20:03:054250 },
[email protected]2d731a32010-04-29 01:04:064251 };
4252
4253 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4254
4255 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4256 scoped_refptr<HttpNetworkSession> session(
4257 SetupSessionForGroupNameTests(tests[i].proxy_server));
4258
4259 HttpNetworkSessionPeer peer(session);
4260
[email protected]e60e47a2010-07-14 03:37:184261 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134262 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4263 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184264 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4265 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4266 new CaptureGroupNameSSLSocketPool(session.get()));
4267 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064268
4269 EXPECT_EQ(ERR_IO_PENDING,
4270 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184271 if (tests[i].ssl)
4272 EXPECT_EQ(tests[i].expected_group_name,
4273 ssl_conn_pool->last_group_name_received());
4274 else
4275 EXPECT_EQ(tests[i].expected_group_name,
4276 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064277 }
4278
4279 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4280}
4281
4282TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4283 const GroupNameTest tests[] = {
4284 {
4285 "socks4://socks_proxy:1080",
4286 "http://www.google.com/socks4_direct",
4287 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184288 false,
[email protected]2d731a32010-04-29 01:04:064289 },
4290 {
4291 "socks5://socks_proxy:1080",
4292 "http://www.google.com/socks5_direct",
4293 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184294 false,
[email protected]2d731a32010-04-29 01:04:064295 },
4296
4297 // SSL Tests
4298 {
4299 "socks4://socks_proxy:1080",
4300 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024301 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184302 true,
[email protected]2d731a32010-04-29 01:04:064303 },
4304 {
4305 "socks5://socks_proxy:1080",
4306 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024307 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184308 true,
[email protected]2d731a32010-04-29 01:04:064309 },
4310
[email protected]9faeded92010-04-29 20:03:054311 {
4312 "socks4://socks_proxy:1080",
4313 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024314 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184315 true,
[email protected]9faeded92010-04-29 20:03:054316 },
[email protected]04e5be32009-06-26 20:00:314317 };
4318
[email protected]2ff8b312010-04-26 22:20:544319 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4320
[email protected]04e5be32009-06-26 20:00:314321 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064322 scoped_refptr<HttpNetworkSession> session(
4323 SetupSessionForGroupNameTests(tests[i].proxy_server));
4324 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314325
[email protected]e60e47a2010-07-14 03:37:184326 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264327 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064328 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184329 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4330 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4331 new CaptureGroupNameSSLSocketPool(session.get()));
4332 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314333
[email protected]5695b8c2009-09-30 21:36:434334 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314335
[email protected]2d731a32010-04-29 01:04:064336 EXPECT_EQ(ERR_IO_PENDING,
4337 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184338 if (tests[i].ssl)
4339 EXPECT_EQ(tests[i].expected_group_name,
4340 ssl_conn_pool->last_group_name_received());
4341 else
4342 EXPECT_EQ(tests[i].expected_group_name,
4343 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314344 }
[email protected]2ff8b312010-04-26 22:20:544345
4346 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314347}
4348
[email protected]9172a982009-06-06 00:30:254349TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544350 SessionDependencies session_deps(
4351 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324352
[email protected]69719062010-01-05 20:09:214353 // This simulates failure resolving all hostnames; that means we will fail
4354 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324355 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4356
[email protected]9172a982009-06-06 00:30:254357 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434358 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254359
4360 HttpRequestInfo request;
4361 request.method = "GET";
4362 request.url = GURL("http://www.google.com/");
4363
4364 TestCompletionCallback callback;
4365
[email protected]5a1d7ca2010-04-28 20:12:274366 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254367 EXPECT_EQ(ERR_IO_PENDING, rv);
4368
[email protected]9172a982009-06-06 00:30:254369 rv = callback.WaitForResult();
4370 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4371}
4372
[email protected]f3e6c1e2009-06-15 20:52:124373// Host resolution observer used by
4374// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4375// resovle requests are issued with a referrer of |expected_referrer|.
4376class ResolutionReferrerObserver : public HostResolver::Observer {
4377 public:
4378 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4379 : expected_referrer_(expected_referrer),
4380 called_start_with_referrer_(false),
4381 called_finish_with_referrer_(false) {
4382 }
4383
4384 virtual void OnStartResolution(int id,
4385 const HostResolver::RequestInfo& info) {
4386 if (info.referrer() == expected_referrer_)
4387 called_start_with_referrer_ = true;
4388 }
4389
4390 virtual void OnFinishResolutionWithStatus(
4391 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4392 if (info.referrer() == expected_referrer_)
4393 called_finish_with_referrer_ = true;
4394 }
4395
[email protected]eb255d32009-06-17 02:11:034396 virtual void OnCancelResolution(int id,
4397 const HostResolver::RequestInfo& info ) {
4398 FAIL() << "Should not be cancelling any requests!";
4399 }
4400
[email protected]f3e6c1e2009-06-15 20:52:124401 bool did_complete_with_expected_referrer() const {
4402 return called_start_with_referrer_ && called_finish_with_referrer_;
4403 }
4404
4405 private:
4406 GURL expected_referrer_;
4407 bool called_start_with_referrer_;
4408 bool called_finish_with_referrer_;
4409
4410 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4411};
4412
4413// Make sure that when HostResolver::Resolve() is invoked, it passes through
4414// the "referrer". This is depended on by the DNS prefetch observer.
4415TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4416 GURL referrer = GURL("http://expected-referrer/");
4417 EXPECT_TRUE(referrer.is_valid());
4418 ResolutionReferrerObserver resolution_observer(referrer);
4419
4420 SessionDependencies session_deps;
4421 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434422 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124423
4424 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144425 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124426
4427 // Connect up a mock socket which will fail when reading.
4428 MockRead data_reads[] = {
4429 MockRead(false, ERR_FAILED),
4430 };
[email protected]31a2bfe2010-02-09 08:03:394431 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594432 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124433
4434 // Issue a request, containing an HTTP referrer.
4435 HttpRequestInfo request;
4436 request.method = "GET";
4437 request.referrer = referrer;
4438 request.url = GURL("http://www.google.com/");
4439
4440 // Run the request until it fails reading from the socket.
4441 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274442 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124443 EXPECT_EQ(ERR_IO_PENDING, rv);
4444 rv = callback.WaitForResult();
4445 EXPECT_EQ(ERR_FAILED, rv);
4446
4447 // Check that the host resolution observer saw |referrer|.
4448 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4449}
4450
[email protected]685af592010-05-11 19:31:244451// Base test to make sure that when the load flags for a request specify to
4452// bypass the cache, the DNS cache is not used.
4453void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284454 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324455
[email protected]a2c2fb92009-07-18 07:31:044456 // Select a host resolver that does caching.
4457 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324458
[email protected]3b9cca42009-06-16 01:08:284459 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434460 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284461
4462 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4463 // a synchronous lookup.)
4464 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144465 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464466 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274467 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284468 EXPECT_EQ(OK, rv);
4469
4470 // Verify that it was added to host cache, by doing a subsequent async lookup
4471 // and confirming it completes synchronously.
4472 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464473 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284474 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274475 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324476 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284477
4478 // Inject a failure the next time that "www.google.com" is resolved. This way
4479 // we can tell if the next lookup hit the cache, or the "network".
4480 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324481 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284482
4483 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4484 // first read -- this won't be reached as the host resolution will fail first.
4485 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394486 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594487 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284488
4489 // Issue a request, asking to bypass the cache(s).
4490 HttpRequestInfo request;
4491 request.method = "GET";
[email protected]685af592010-05-11 19:31:244492 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284493 request.url = GURL("http://www.google.com/");
4494
4495 // Run the request.
4496 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274497 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284498 ASSERT_EQ(ERR_IO_PENDING, rv);
4499 rv = callback.WaitForResult();
4500
4501 // If we bypassed the cache, we would have gotten a failure while resolving
4502 // "www.google.com".
4503 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4504}
4505
[email protected]685af592010-05-11 19:31:244506// There are multiple load flags that should trigger the host cache bypass.
4507// Test each in isolation:
4508TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4509 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4510}
4511
4512TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4513 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4514}
4515
4516TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4517 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4518}
4519
[email protected]0877e3d2009-10-17 22:29:574520// Make sure we can handle an error when writing the request.
4521TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4522 SessionDependencies session_deps;
4523 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4524
4525 HttpRequestInfo request;
4526 request.method = "GET";
4527 request.url = GURL("http://www.foo.com/");
4528 request.load_flags = 0;
4529
4530 MockWrite write_failure[] = {
4531 MockWrite(true, ERR_CONNECTION_RESET),
4532 };
[email protected]31a2bfe2010-02-09 08:03:394533 StaticSocketDataProvider data(NULL, 0,
4534 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594535 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574536
4537 TestCompletionCallback callback;
4538
4539 scoped_ptr<HttpTransaction> trans(
4540 new HttpNetworkTransaction(CreateSession(&session_deps)));
4541
[email protected]5a1d7ca2010-04-28 20:12:274542 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574543 EXPECT_EQ(ERR_IO_PENDING, rv);
4544
4545 rv = callback.WaitForResult();
4546 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4547}
4548
4549// Check that a connection closed after the start of the headers finishes ok.
4550TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4551 SessionDependencies session_deps;
4552 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4553
4554 HttpRequestInfo request;
4555 request.method = "GET";
4556 request.url = GURL("http://www.foo.com/");
4557 request.load_flags = 0;
4558
4559 MockRead data_reads[] = {
4560 MockRead("HTTP/1."),
4561 MockRead(false, OK),
4562 };
4563
[email protected]31a2bfe2010-02-09 08:03:394564 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594565 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574566
4567 TestCompletionCallback callback;
4568
4569 scoped_ptr<HttpTransaction> trans(
4570 new HttpNetworkTransaction(CreateSession(&session_deps)));
4571
[email protected]5a1d7ca2010-04-28 20:12:274572 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574573 EXPECT_EQ(ERR_IO_PENDING, rv);
4574
4575 rv = callback.WaitForResult();
4576 EXPECT_EQ(OK, rv);
4577
4578 const HttpResponseInfo* response = trans->GetResponseInfo();
4579 EXPECT_TRUE(response != NULL);
4580
4581 EXPECT_TRUE(response->headers != NULL);
4582 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4583
4584 std::string response_data;
4585 rv = ReadTransaction(trans.get(), &response_data);
4586 EXPECT_EQ(OK, rv);
4587 EXPECT_EQ("", response_data);
4588}
4589
4590// Make sure that a dropped connection while draining the body for auth
4591// restart does the right thing.
4592TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4593 SessionDependencies session_deps;
4594 scoped_ptr<HttpTransaction> trans(
4595 new HttpNetworkTransaction(CreateSession(&session_deps)));
4596
4597 HttpRequestInfo request;
4598 request.method = "GET";
4599 request.url = GURL("http://www.google.com/");
4600 request.load_flags = 0;
4601
4602 MockWrite data_writes1[] = {
4603 MockWrite("GET / HTTP/1.1\r\n"
4604 "Host: www.google.com\r\n"
4605 "Connection: keep-alive\r\n\r\n"),
4606 };
4607
4608 MockRead data_reads1[] = {
4609 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4610 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4611 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4612 MockRead("Content-Length: 14\r\n\r\n"),
4613 MockRead("Unauth"),
4614 MockRead(true, ERR_CONNECTION_RESET),
4615 };
4616
[email protected]31a2bfe2010-02-09 08:03:394617 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4618 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594619 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574620
4621 // After calling trans->RestartWithAuth(), this is the request we should
4622 // be issuing -- the final header line contains the credentials.
4623 MockWrite data_writes2[] = {
4624 MockWrite("GET / HTTP/1.1\r\n"
4625 "Host: www.google.com\r\n"
4626 "Connection: keep-alive\r\n"
4627 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4628 };
4629
4630 // Lastly, the server responds with the actual content.
4631 MockRead data_reads2[] = {
4632 MockRead("HTTP/1.1 200 OK\r\n"),
4633 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4634 MockRead("Content-Length: 100\r\n\r\n"),
4635 MockRead(false, OK),
4636 };
4637
[email protected]31a2bfe2010-02-09 08:03:394638 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4639 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594640 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574641
4642 TestCompletionCallback callback1;
4643
[email protected]5a1d7ca2010-04-28 20:12:274644 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574645 EXPECT_EQ(ERR_IO_PENDING, rv);
4646
4647 rv = callback1.WaitForResult();
4648 EXPECT_EQ(OK, rv);
4649
4650 const HttpResponseInfo* response = trans->GetResponseInfo();
4651 EXPECT_FALSE(response == NULL);
4652
4653 // The password prompt info should have been set in response->auth_challenge.
4654 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4655
4656 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4657 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4658 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4659
4660 TestCompletionCallback callback2;
4661
[email protected]13c8a092010-07-29 06:15:444662 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:574663 EXPECT_EQ(ERR_IO_PENDING, rv);
4664
4665 rv = callback2.WaitForResult();
4666 EXPECT_EQ(OK, rv);
4667
4668 response = trans->GetResponseInfo();
4669 EXPECT_FALSE(response == NULL);
4670 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4671 EXPECT_EQ(100, response->headers->GetContentLength());
4672}
4673
4674// Test HTTPS connections going through a proxy that sends extra data.
4675TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4676 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4677
4678 HttpRequestInfo request;
4679 request.method = "GET";
4680 request.url = GURL("https://www.google.com/");
4681 request.load_flags = 0;
4682
4683 MockRead proxy_reads[] = {
4684 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4685 MockRead(false, OK)
4686 };
4687
[email protected]31a2bfe2010-02-09 08:03:394688 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594689 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574690
[email protected]5ecc992a42009-11-11 01:41:594691 session_deps.socket_factory.AddSocketDataProvider(&data);
4692 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574693
4694 TestCompletionCallback callback;
4695
4696 session_deps.socket_factory.ResetNextMockIndexes();
4697
4698 scoped_ptr<HttpTransaction> trans(
4699 new HttpNetworkTransaction(CreateSession(&session_deps)));
4700
[email protected]5a1d7ca2010-04-28 20:12:274701 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574702 EXPECT_EQ(ERR_IO_PENDING, rv);
4703
4704 rv = callback.WaitForResult();
4705 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4706}
4707
[email protected]e22e1362009-11-23 21:31:124708TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464709 SessionDependencies session_deps;
4710 scoped_ptr<HttpTransaction> trans(
4711 new HttpNetworkTransaction(CreateSession(&session_deps)));
4712
4713 HttpRequestInfo request;
4714 request.method = "GET";
4715 request.url = GURL("http://www.google.com/");
4716 request.load_flags = 0;
4717
[email protected]e22e1362009-11-23 21:31:124718 MockRead data_reads[] = {
4719 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4720 MockRead(false, OK),
4721 };
[email protected]9492e4a2010-02-24 00:58:464722
4723 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4724 session_deps.socket_factory.AddSocketDataProvider(&data);
4725
4726 TestCompletionCallback callback;
4727
[email protected]5a1d7ca2010-04-28 20:12:274728 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464729 EXPECT_EQ(ERR_IO_PENDING, rv);
4730
4731 EXPECT_EQ(OK, callback.WaitForResult());
4732
4733 const HttpResponseInfo* response = trans->GetResponseInfo();
4734 EXPECT_TRUE(response != NULL);
4735
4736 EXPECT_TRUE(response->headers != NULL);
4737 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4738
4739 std::string response_data;
4740 rv = ReadTransaction(trans.get(), &response_data);
4741 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124742}
4743
[email protected]95d88ffe2010-02-04 21:25:334744TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4745 SessionDependencies session_deps;
4746 scoped_ptr<HttpTransaction> trans(
4747 new HttpNetworkTransaction(CreateSession(&session_deps)));
4748
4749 HttpRequestInfo request;
4750 request.method = "POST";
4751 request.url = GURL("http://www.google.com/upload");
4752 request.upload_data = new UploadData;
4753 request.load_flags = 0;
4754
4755 FilePath temp_file_path;
4756 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4757 const uint64 kFakeSize = 100000; // file is actually blank
4758
4759 std::vector<UploadData::Element> elements;
4760 UploadData::Element element;
4761 element.SetToFilePath(temp_file_path);
4762 element.SetContentLength(kFakeSize);
4763 elements.push_back(element);
4764 request.upload_data->set_elements(elements);
4765 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4766
4767 MockRead data_reads[] = {
4768 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4769 MockRead("hello world"),
4770 MockRead(false, OK),
4771 };
[email protected]31a2bfe2010-02-09 08:03:394772 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334773 session_deps.socket_factory.AddSocketDataProvider(&data);
4774
4775 TestCompletionCallback callback;
4776
[email protected]5a1d7ca2010-04-28 20:12:274777 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334778 EXPECT_EQ(ERR_IO_PENDING, rv);
4779
4780 rv = callback.WaitForResult();
4781 EXPECT_EQ(OK, rv);
4782
4783 const HttpResponseInfo* response = trans->GetResponseInfo();
4784 EXPECT_TRUE(response != NULL);
4785
4786 EXPECT_TRUE(response->headers != NULL);
4787 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4788
4789 std::string response_data;
4790 rv = ReadTransaction(trans.get(), &response_data);
4791 EXPECT_EQ(OK, rv);
4792 EXPECT_EQ("hello world", response_data);
4793
4794 file_util::Delete(temp_file_path, false);
4795}
4796
[email protected]6624b4622010-03-29 19:58:364797TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4798 // If we try to upload an unreadable file, the network stack should report
4799 // the file size as zero and upload zero bytes for that file.
4800 SessionDependencies session_deps;
4801 scoped_ptr<HttpTransaction> trans(
4802 new HttpNetworkTransaction(CreateSession(&session_deps)));
4803
4804 FilePath temp_file;
4805 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4806 std::string temp_file_content("Unreadable file.");
4807 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4808 temp_file_content.length()));
4809 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4810
4811 HttpRequestInfo request;
4812 request.method = "POST";
4813 request.url = GURL("http://www.google.com/upload");
4814 request.upload_data = new UploadData;
4815 request.load_flags = 0;
4816
4817 std::vector<UploadData::Element> elements;
4818 UploadData::Element element;
4819 element.SetToFilePath(temp_file);
4820 elements.push_back(element);
4821 request.upload_data->set_elements(elements);
4822
4823 MockRead data_reads[] = {
4824 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4825 MockRead(false, OK),
4826 };
4827 MockWrite data_writes[] = {
4828 MockWrite("POST /upload HTTP/1.1\r\n"
4829 "Host: www.google.com\r\n"
4830 "Connection: keep-alive\r\n"
4831 "Content-Length: 0\r\n\r\n"),
4832 MockWrite(false, OK),
4833 };
4834 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4835 arraysize(data_writes));
4836 session_deps.socket_factory.AddSocketDataProvider(&data);
4837
4838 TestCompletionCallback callback;
4839
[email protected]5a1d7ca2010-04-28 20:12:274840 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364841 EXPECT_EQ(ERR_IO_PENDING, rv);
4842
4843 rv = callback.WaitForResult();
4844 EXPECT_EQ(OK, rv);
4845
4846 const HttpResponseInfo* response = trans->GetResponseInfo();
4847 EXPECT_TRUE(response != NULL);
4848 EXPECT_TRUE(response->headers != NULL);
4849 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4850
4851 file_util::Delete(temp_file, false);
4852}
4853
4854TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4855 SessionDependencies session_deps;
4856 scoped_ptr<HttpTransaction> trans(
4857 new HttpNetworkTransaction(CreateSession(&session_deps)));
4858
4859 FilePath temp_file;
4860 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4861 std::string temp_file_contents("Unreadable file.");
4862 std::string unreadable_contents(temp_file_contents.length(), '\0');
4863 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4864 temp_file_contents.length()));
4865
4866 HttpRequestInfo request;
4867 request.method = "POST";
4868 request.url = GURL("http://www.google.com/upload");
4869 request.upload_data = new UploadData;
4870 request.load_flags = 0;
4871
4872 std::vector<UploadData::Element> elements;
4873 UploadData::Element element;
4874 element.SetToFilePath(temp_file);
4875 elements.push_back(element);
4876 request.upload_data->set_elements(elements);
4877
4878 MockRead data_reads[] = {
4879 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4880 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4881 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4882
4883 MockRead("HTTP/1.1 200 OK\r\n"),
4884 MockRead("Content-Length: 0\r\n\r\n"),
4885 MockRead(false, OK),
4886 };
4887 MockWrite data_writes[] = {
4888 MockWrite("POST /upload HTTP/1.1\r\n"
4889 "Host: www.google.com\r\n"
4890 "Connection: keep-alive\r\n"
4891 "Content-Length: 16\r\n\r\n"),
4892 MockWrite(false, temp_file_contents.c_str()),
4893
4894 MockWrite("POST /upload HTTP/1.1\r\n"
4895 "Host: www.google.com\r\n"
4896 "Connection: keep-alive\r\n"
4897 "Content-Length: 16\r\n"
4898 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4899 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4900 MockWrite(false, OK),
4901 };
4902 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4903 arraysize(data_writes));
4904 session_deps.socket_factory.AddSocketDataProvider(&data);
4905
4906 TestCompletionCallback callback1;
4907
[email protected]5a1d7ca2010-04-28 20:12:274908 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364909 EXPECT_EQ(ERR_IO_PENDING, rv);
4910
4911 rv = callback1.WaitForResult();
4912 EXPECT_EQ(OK, rv);
4913
4914 const HttpResponseInfo* response = trans->GetResponseInfo();
4915 EXPECT_TRUE(response != NULL);
4916 EXPECT_TRUE(response->headers != NULL);
4917 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4918
4919 // The password prompt info should have been set in response->auth_challenge.
4920 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4921 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4922 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4923 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4924
4925 // Now make the file unreadable and try again.
4926 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4927
4928 TestCompletionCallback callback2;
4929
[email protected]13c8a092010-07-29 06:15:444930 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:364931 EXPECT_EQ(ERR_IO_PENDING, rv);
4932
4933 rv = callback2.WaitForResult();
4934 EXPECT_EQ(OK, rv);
4935
4936 response = trans->GetResponseInfo();
4937 EXPECT_TRUE(response != NULL);
4938 EXPECT_TRUE(response->headers != NULL);
4939 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4940 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4941
4942 file_util::Delete(temp_file, false);
4943}
4944
[email protected]aeefc9e82010-02-19 16:18:274945// Tests that changes to Auth realms are treated like auth rejections.
4946TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4947 SessionDependencies session_deps;
4948 scoped_ptr<HttpTransaction> trans(
4949 new HttpNetworkTransaction(CreateSession(&session_deps)));
4950
4951 HttpRequestInfo request;
4952 request.method = "GET";
4953 request.url = GURL("http://www.google.com/");
4954 request.load_flags = 0;
4955
4956 // First transaction will request a resource and receive a Basic challenge
4957 // with realm="first_realm".
4958 MockWrite data_writes1[] = {
4959 MockWrite("GET / HTTP/1.1\r\n"
4960 "Host: www.google.com\r\n"
4961 "Connection: keep-alive\r\n"
4962 "\r\n"),
4963 };
4964 MockRead data_reads1[] = {
4965 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4966 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4967 "\r\n"),
4968 };
4969
4970 // After calling trans->RestartWithAuth(), provide an Authentication header
4971 // for first_realm. The server will reject and provide a challenge with
4972 // second_realm.
4973 MockWrite data_writes2[] = {
4974 MockWrite("GET / HTTP/1.1\r\n"
4975 "Host: www.google.com\r\n"
4976 "Connection: keep-alive\r\n"
4977 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4978 "\r\n"),
4979 };
4980 MockRead data_reads2[] = {
4981 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4982 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4983 "\r\n"),
4984 };
4985
4986 // This again fails, and goes back to first_realm. Make sure that the
4987 // entry is removed from cache.
4988 MockWrite data_writes3[] = {
4989 MockWrite("GET / HTTP/1.1\r\n"
4990 "Host: www.google.com\r\n"
4991 "Connection: keep-alive\r\n"
4992 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4993 "\r\n"),
4994 };
4995 MockRead data_reads3[] = {
4996 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4997 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4998 "\r\n"),
4999 };
5000
5001 // Try one last time (with the correct password) and get the resource.
5002 MockWrite data_writes4[] = {
5003 MockWrite("GET / HTTP/1.1\r\n"
5004 "Host: www.google.com\r\n"
5005 "Connection: keep-alive\r\n"
5006 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5007 "\r\n"),
5008 };
5009 MockRead data_reads4[] = {
5010 MockRead("HTTP/1.1 200 OK\r\n"
5011 "Content-Type: text/html; charset=iso-8859-1\r\n"
5012 "Content-Length: 100\r\n"
5013 "\r\n"),
5014 };
5015
5016 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5017 data_writes1, arraysize(data_writes1));
5018 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5019 data_writes2, arraysize(data_writes2));
5020 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5021 data_writes3, arraysize(data_writes3));
5022 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5023 data_writes4, arraysize(data_writes4));
5024 session_deps.socket_factory.AddSocketDataProvider(&data1);
5025 session_deps.socket_factory.AddSocketDataProvider(&data2);
5026 session_deps.socket_factory.AddSocketDataProvider(&data3);
5027 session_deps.socket_factory.AddSocketDataProvider(&data4);
5028
5029 TestCompletionCallback callback1;
5030
5031 // Issue the first request with Authorize headers. There should be a
5032 // password prompt for first_realm waiting to be filled in after the
5033 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275034 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275035 EXPECT_EQ(ERR_IO_PENDING, rv);
5036 rv = callback1.WaitForResult();
5037 EXPECT_EQ(OK, rv);
5038 const HttpResponseInfo* response = trans->GetResponseInfo();
5039 ASSERT_FALSE(response == NULL);
5040 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5041 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5042 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5043 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5044
5045 // Issue the second request with an incorrect password. There should be a
5046 // password prompt for second_realm waiting to be filled in after the
5047 // transaction completes.
5048 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445049 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275050 EXPECT_EQ(ERR_IO_PENDING, rv);
5051 rv = callback2.WaitForResult();
5052 EXPECT_EQ(OK, rv);
5053 response = trans->GetResponseInfo();
5054 ASSERT_FALSE(response == NULL);
5055 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5056 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5057 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5058 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5059
5060 // Issue the third request with another incorrect password. There should be
5061 // a password prompt for first_realm waiting to be filled in. If the password
5062 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5063 // first_realm was not correctly removed.
5064 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445065 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275066 EXPECT_EQ(ERR_IO_PENDING, rv);
5067 rv = callback3.WaitForResult();
5068 EXPECT_EQ(OK, rv);
5069 response = trans->GetResponseInfo();
5070 ASSERT_FALSE(response == NULL);
5071 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5072 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5073 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5074 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5075
5076 // Issue the fourth request with the correct password and username.
5077 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445078 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275079 EXPECT_EQ(ERR_IO_PENDING, rv);
5080 rv = callback4.WaitForResult();
5081 EXPECT_EQ(OK, rv);
5082 response = trans->GetResponseInfo();
5083 ASSERT_FALSE(response == NULL);
5084 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5085}
5086
[email protected]564b4912010-03-09 16:30:425087TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:425088 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:065089 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:425090
[email protected]564b4912010-03-09 16:30:425091 SessionDependencies session_deps;
5092
5093 MockRead data_reads[] = {
5094 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355095 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425096 MockRead("hello world"),
5097 MockRead(false, OK),
5098 };
5099
5100 HttpRequestInfo request;
5101 request.method = "GET";
5102 request.url = GURL("http://www.google.com/");
5103 request.load_flags = 0;
5104
5105 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5106
5107 session_deps.socket_factory.AddSocketDataProvider(&data);
5108
5109 TestCompletionCallback callback;
5110
5111 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5112 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5113
[email protected]5a1d7ca2010-04-28 20:12:275114 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425115 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535116
[email protected]2fbaecf22010-07-22 22:20:355117 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425118 const HttpAlternateProtocols& alternate_protocols =
5119 session->alternate_protocols();
5120 EXPECT_FALSE(
5121 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5122
5123 EXPECT_EQ(OK, callback.WaitForResult());
5124
5125 const HttpResponseInfo* response = trans->GetResponseInfo();
5126 ASSERT_TRUE(response != NULL);
5127 ASSERT_TRUE(response->headers != NULL);
5128 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535129 EXPECT_FALSE(response->was_fetched_via_spdy);
5130 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575131 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425132
5133 std::string response_data;
5134 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5135 EXPECT_EQ("hello world", response_data);
5136
5137 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5138 const HttpAlternateProtocols::PortProtocolPair alternate =
5139 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5140 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5141 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355142 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425143 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425144
[email protected]31e2c69e2010-04-15 18:06:065145 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:425146 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:425147}
5148
5149TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:065150 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:425151 SessionDependencies session_deps;
5152
5153 HttpRequestInfo request;
5154 request.method = "GET";
5155 request.url = GURL("http://www.google.com/");
5156 request.load_flags = 0;
5157
5158 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5159 StaticSocketDataProvider first_data;
5160 first_data.set_connect_data(mock_connect);
5161 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5162
5163 MockRead data_reads[] = {
5164 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5165 MockRead("hello world"),
5166 MockRead(true, OK),
5167 };
5168 StaticSocketDataProvider second_data(
5169 data_reads, arraysize(data_reads), NULL, 0);
5170 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5171
5172 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5173 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5174 // http://crbug.com/37454.
5175 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5176
5177 TestCompletionCallback callback;
5178
5179 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5180
[email protected]2fbaecf22010-07-22 22:20:355181 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425182 HttpAlternateProtocols* alternate_protocols =
5183 session->mutable_alternate_protocols();
5184 alternate_protocols->SetAlternateProtocolFor(
5185 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355186 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425187
5188 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5189
[email protected]5a1d7ca2010-04-28 20:12:275190 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425191 EXPECT_EQ(ERR_IO_PENDING, rv);
5192 EXPECT_EQ(OK, callback.WaitForResult());
5193
5194 const HttpResponseInfo* response = trans->GetResponseInfo();
5195 ASSERT_TRUE(response != NULL);
5196 ASSERT_TRUE(response->headers != NULL);
5197 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5198
5199 std::string response_data;
5200 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5201 EXPECT_EQ("hello world", response_data);
5202
5203 ASSERT_TRUE(
5204 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5205 const HttpAlternateProtocols::PortProtocolPair alternate =
5206 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5207 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065208 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425209}
5210
5211// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5212// says that it does SPDY, but it just does the TLS handshake, but the NPN
5213// response does not indicate SPDY, so we just do standard HTTPS over the port.
5214// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5215// on the original port.
[email protected]a2cb8122010-03-10 17:22:425216// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5217// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535218//
[email protected]a2cb8122010-03-10 17:22:425219// HttpRequestInfo request;
5220// request.method = "GET";
5221// request.url = GURL("http://www.google.com/");
5222// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535223//
[email protected]a2cb8122010-03-10 17:22:425224// MockRead data_reads[] = {
5225// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5226// MockRead("hello world"),
5227// MockRead(true, OK),
5228// };
5229// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5230// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535231//
[email protected]a2cb8122010-03-10 17:22:425232// SSLSocketDataProvider ssl(true, OK);
5233// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535234//
[email protected]a2cb8122010-03-10 17:22:425235// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535236//
[email protected]a2cb8122010-03-10 17:22:425237// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535238//
[email protected]a2cb8122010-03-10 17:22:425239// HostPortPair http_host_port_pair;
5240// http_host_port_pair.host = "www.google.com";
5241// http_host_port_pair.port = 80;
5242// HttpAlternateProtocols* alternate_protocols =
5243// session->mutable_alternate_protocols();
5244// alternate_protocols->SetAlternateProtocolFor(
5245// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065246// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535247//
[email protected]a2cb8122010-03-10 17:22:425248// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535249//
[email protected]5a1d7ca2010-04-28 20:12:275250// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425251// EXPECT_EQ(ERR_IO_PENDING, rv);
5252// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535253//
[email protected]a2cb8122010-03-10 17:22:425254// const HttpResponseInfo* response = trans->GetResponseInfo();
5255// ASSERT_TRUE(response != NULL);
5256// ASSERT_TRUE(response->headers != NULL);
5257// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535258//
[email protected]a2cb8122010-03-10 17:22:425259// std::string response_data;
5260// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5261// EXPECT_EQ("hello world", response_data);
5262// }
5263
5264TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065265 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355266 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425267 SessionDependencies session_deps;
5268
5269 HttpRequestInfo request;
5270 request.method = "GET";
5271 request.url = GURL("http://www.google.com/");
5272 request.load_flags = 0;
5273
[email protected]a2cb8122010-03-10 17:22:425274 StaticSocketDataProvider first_tcp_connect;
5275 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5276
5277 SSLSocketDataProvider ssl(true, OK);
5278 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5279
[email protected]564b4912010-03-09 16:30:425280 MockRead data_reads[] = {
5281 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5282 MockRead("hello world"),
5283 MockRead(true, OK),
5284 };
[email protected]a2cb8122010-03-10 17:22:425285 StaticSocketDataProvider fallback_data(
5286 data_reads, arraysize(data_reads), NULL, 0);
5287 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425288
5289 TestCompletionCallback callback;
5290
5291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5292
[email protected]2fbaecf22010-07-22 22:20:355293 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425294 HttpAlternateProtocols* alternate_protocols =
5295 session->mutable_alternate_protocols();
5296 alternate_protocols->SetAlternateProtocolFor(
5297 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355298 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425299
5300 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5301
[email protected]5a1d7ca2010-04-28 20:12:275302 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425303 EXPECT_EQ(ERR_IO_PENDING, rv);
5304 EXPECT_EQ(OK, callback.WaitForResult());
5305
5306 const HttpResponseInfo* response = trans->GetResponseInfo();
5307 ASSERT_TRUE(response != NULL);
5308 ASSERT_TRUE(response->headers != NULL);
5309 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5310
5311 std::string response_data;
5312 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5313 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545314 HttpNetworkTransaction::SetNextProtos("");
5315 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5316}
5317
5318TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5319 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355320 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545321 SessionDependencies session_deps;
5322
5323 HttpRequestInfo request;
5324 request.method = "GET";
5325 request.url = GURL("http://www.google.com/");
5326 request.load_flags = 0;
5327
5328 MockRead data_reads[] = {
5329 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355330 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545331 MockRead("hello world"),
5332 MockRead(true, OK),
5333 };
5334
5335 StaticSocketDataProvider first_transaction(
5336 data_reads, arraysize(data_reads), NULL, 0);
5337 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5338
5339 SSLSocketDataProvider ssl(true, OK);
5340 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355341 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535342 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5344
[email protected]2bd93022010-07-17 00:58:445345 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135346 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545347
[email protected]2bd93022010-07-17 00:58:445348 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5349 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545350 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135351 CreateMockRead(*resp),
5352 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545353 MockRead(true, 0, 0),
5354 };
5355
5356 scoped_refptr<DelayedSocketData> spdy_data(
5357 new DelayedSocketData(
5358 1, // wait for one write to finish before reading.
5359 spdy_reads, arraysize(spdy_reads),
5360 spdy_writes, arraysize(spdy_writes)));
5361 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5362
5363 TestCompletionCallback callback;
5364
5365 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5366 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5367
[email protected]5a1d7ca2010-04-28 20:12:275368 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545369 EXPECT_EQ(ERR_IO_PENDING, rv);
5370 EXPECT_EQ(OK, callback.WaitForResult());
5371
5372 const HttpResponseInfo* response = trans->GetResponseInfo();
5373 ASSERT_TRUE(response != NULL);
5374 ASSERT_TRUE(response->headers != NULL);
5375 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5376
5377 std::string response_data;
5378 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5379 EXPECT_EQ("hello world", response_data);
5380
5381 trans.reset(new HttpNetworkTransaction(session));
5382
[email protected]5a1d7ca2010-04-28 20:12:275383 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545384 EXPECT_EQ(ERR_IO_PENDING, rv);
5385 EXPECT_EQ(OK, callback.WaitForResult());
5386
5387 response = trans->GetResponseInfo();
5388 ASSERT_TRUE(response != NULL);
5389 ASSERT_TRUE(response->headers != NULL);
5390 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535391 EXPECT_TRUE(response->was_fetched_via_spdy);
5392 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575393 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545394
5395 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5396 EXPECT_EQ("hello!", response_data);
5397
5398 HttpNetworkTransaction::SetNextProtos("");
5399 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5400}
5401
[email protected]631f1322010-04-30 17:59:115402class CapturingProxyResolver : public ProxyResolver {
5403 public:
5404 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5405 virtual ~CapturingProxyResolver() {}
5406
5407 virtual int GetProxyForURL(const GURL& url,
5408 ProxyInfo* results,
5409 CompletionCallback* callback,
5410 RequestHandle* request,
5411 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:405412 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
5413 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:425414 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115415 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425416 return OK;
[email protected]631f1322010-04-30 17:59:115417 }
5418
5419 virtual void CancelRequest(RequestHandle request) {
5420 NOTREACHED();
5421 }
5422
[email protected]24476402010-07-20 20:55:175423 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:115424 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425425 return OK;
[email protected]631f1322010-04-30 17:59:115426 }
5427
[email protected]24476402010-07-20 20:55:175428 const std::vector<GURL>& resolved() const { return resolved_; }
5429
5430 private:
[email protected]631f1322010-04-30 17:59:115431 std::vector<GURL> resolved_;
5432
5433 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5434};
5435
[email protected]631f1322010-04-30 17:59:115436TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5437 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355438 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:115439
5440 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425441 proxy_config.set_auto_detect(true);
5442 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115443
[email protected]631f1322010-04-30 17:59:115444 CapturingProxyResolver* capturing_proxy_resolver =
5445 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385446 SessionDependencies session_deps(new ProxyService(
5447 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5448 NULL));
[email protected]631f1322010-04-30 17:59:115449
5450 HttpRequestInfo request;
5451 request.method = "GET";
5452 request.url = GURL("http://www.google.com/");
5453 request.load_flags = 0;
5454
5455 MockRead data_reads[] = {
5456 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355457 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:115458 MockRead("hello world"),
5459 MockRead(true, OK),
5460 };
5461
5462 StaticSocketDataProvider first_transaction(
5463 data_reads, arraysize(data_reads), NULL, 0);
5464 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5465
5466 SSLSocketDataProvider ssl(true, OK);
5467 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355468 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535469 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115470 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5471
[email protected]2bd93022010-07-17 00:58:445472 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:115473 MockWrite spdy_writes[] = {
5474 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5475 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425476 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135477 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115478 };
5479
[email protected]d911f1b2010-05-05 22:39:425480 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5481
[email protected]2bd93022010-07-17 00:58:445482 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5483 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:115484 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425485 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135486 CreateMockRead(*resp.get(), 4), // 2, 4
5487 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425488 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115489 };
5490
[email protected]d911f1b2010-05-05 22:39:425491 scoped_refptr<OrderedSocketData> spdy_data(
5492 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115493 spdy_reads, arraysize(spdy_reads),
5494 spdy_writes, arraysize(spdy_writes)));
5495 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5496
5497 TestCompletionCallback callback;
5498
5499 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5500 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5501
5502 int rv = trans->Start(&request, &callback, BoundNetLog());
5503 EXPECT_EQ(ERR_IO_PENDING, rv);
5504 EXPECT_EQ(OK, callback.WaitForResult());
5505
5506 const HttpResponseInfo* response = trans->GetResponseInfo();
5507 ASSERT_TRUE(response != NULL);
5508 ASSERT_TRUE(response->headers != NULL);
5509 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535510 EXPECT_FALSE(response->was_fetched_via_spdy);
5511 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115512
5513 std::string response_data;
5514 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5515 EXPECT_EQ("hello world", response_data);
5516
5517 trans.reset(new HttpNetworkTransaction(session));
5518
5519 rv = trans->Start(&request, &callback, BoundNetLog());
5520 EXPECT_EQ(ERR_IO_PENDING, rv);
5521 EXPECT_EQ(OK, callback.WaitForResult());
5522
5523 response = trans->GetResponseInfo();
5524 ASSERT_TRUE(response != NULL);
5525 ASSERT_TRUE(response->headers != NULL);
5526 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535527 EXPECT_TRUE(response->was_fetched_via_spdy);
5528 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115529
5530 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5531 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425532 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5533 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115534 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425535 EXPECT_EQ("https://www.google.com/",
5536 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115537
5538 HttpNetworkTransaction::SetNextProtos("");
5539 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5540}
[email protected]631f1322010-04-30 17:59:115541
[email protected]2ff8b312010-04-26 22:20:545542TEST_F(HttpNetworkTransactionTest,
5543 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5544 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355545 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545546 SessionDependencies session_deps;
5547
5548 HttpRequestInfo request;
5549 request.method = "GET";
5550 request.url = GURL("http://www.google.com/");
5551 request.load_flags = 0;
5552
5553 MockRead data_reads[] = {
5554 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355555 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545556 MockRead("hello world"),
5557 MockRead(true, OK),
5558 };
5559
5560 StaticSocketDataProvider first_transaction(
5561 data_reads, arraysize(data_reads), NULL, 0);
5562 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5563
5564 SSLSocketDataProvider ssl(true, OK);
5565 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355566 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535567 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545568 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535569 // Make sure we use ssl for spdy here.
5570 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545571
[email protected]2bd93022010-07-17 00:58:445572 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135573 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545574
[email protected]2bd93022010-07-17 00:58:445575 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5576 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545577 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135578 CreateMockRead(*resp),
5579 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545580 MockRead(true, 0, 0),
5581 };
5582
5583 scoped_refptr<DelayedSocketData> spdy_data(
5584 new DelayedSocketData(
5585 1, // wait for one write to finish before reading.
5586 spdy_reads, arraysize(spdy_reads),
5587 spdy_writes, arraysize(spdy_writes)));
5588 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5589
5590 TestCompletionCallback callback;
5591
5592 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5593
5594 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5595
[email protected]5a1d7ca2010-04-28 20:12:275596 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545597 EXPECT_EQ(ERR_IO_PENDING, rv);
5598 EXPECT_EQ(OK, callback.WaitForResult());
5599
5600 const HttpResponseInfo* response = trans->GetResponseInfo();
5601 ASSERT_TRUE(response != NULL);
5602 ASSERT_TRUE(response->headers != NULL);
5603 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5604
5605 std::string response_data;
5606 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5607 EXPECT_EQ("hello world", response_data);
5608
5609 // Set up an initial SpdySession in the pool to reuse.
[email protected]b261d0e2010-08-02 19:13:245610 HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT");
[email protected]2ff8b312010-04-26 22:20:545611 scoped_refptr<SpdySession> spdy_session =
[email protected]b261d0e2010-08-02 19:13:245612 session->spdy_session_pool()->Get(pair, session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215613 scoped_refptr<TCPSocketParams> tcp_params =
5614 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365615 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545616 trans.reset(new HttpNetworkTransaction(session));
5617
[email protected]5a1d7ca2010-04-28 20:12:275618 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545619 EXPECT_EQ(ERR_IO_PENDING, rv);
5620 EXPECT_EQ(OK, callback.WaitForResult());
5621
5622 response = trans->GetResponseInfo();
5623 ASSERT_TRUE(response != NULL);
5624 ASSERT_TRUE(response->headers != NULL);
5625 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535626 EXPECT_TRUE(response->was_fetched_via_spdy);
5627 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575628 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545629
5630 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5631 EXPECT_EQ("hello!", response_data);
5632
5633 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065634 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425635}
5636
[email protected]044de0642010-06-17 10:42:155637// GenerateAuthToken is a mighty big test.
5638// It tests all permutation of GenerateAuthToken behavior:
5639// - Synchronous and Asynchronous completion.
5640// - OK or error on completion.
5641// - Direct connection, non-authenticating proxy, and authenticating proxy.
5642// - HTTP or HTTPS backend (to include proxy tunneling).
5643// - Non-authenticating and authenticating backend.
5644//
5645// In all, there are 44 reasonable permuations (for example, if there are
5646// problems generating an auth token for an authenticating proxy, we don't
5647// need to test all permutations of the backend server).
5648//
5649// The test proceeds by going over each of the configuration cases, and
5650// potentially running up to three rounds in each of the tests. The TestConfig
5651// specifies both the configuration for the test as well as the expectations
5652// for the results.
5653TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5654 const char* kServer = "http://www.example.com";
5655 const char* kSecureServer = "https://www.example.com";
5656 const char* kProxy = "myproxy:70";
5657 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5658
5659 enum AuthTiming {
5660 AUTH_NONE,
5661 AUTH_SYNC,
5662 AUTH_ASYNC,
5663 };
5664
5665 const MockWrite kGet(
5666 "GET / HTTP/1.1\r\n"
5667 "Host: www.example.com\r\n"
5668 "Connection: keep-alive\r\n\r\n");
5669 const MockWrite kGetProxy(
5670 "GET http://www.example.com/ HTTP/1.1\r\n"
5671 "Host: www.example.com\r\n"
5672 "Proxy-Connection: keep-alive\r\n\r\n");
5673 const MockWrite kGetAuth(
5674 "GET / HTTP/1.1\r\n"
5675 "Host: www.example.com\r\n"
5676 "Connection: keep-alive\r\n"
5677 "Authorization: auth_token\r\n\r\n");
5678 const MockWrite kGetProxyAuth(
5679 "GET http://www.example.com/ HTTP/1.1\r\n"
5680 "Host: www.example.com\r\n"
5681 "Proxy-Connection: keep-alive\r\n"
5682 "Proxy-Authorization: auth_token\r\n\r\n");
5683 const MockWrite kGetAuthThroughProxy(
5684 "GET http://www.example.com/ HTTP/1.1\r\n"
5685 "Host: www.example.com\r\n"
5686 "Proxy-Connection: keep-alive\r\n"
5687 "Authorization: auth_token\r\n\r\n");
5688 const MockWrite kGetAuthWithProxyAuth(
5689 "GET http://www.example.com/ HTTP/1.1\r\n"
5690 "Host: www.example.com\r\n"
5691 "Proxy-Connection: keep-alive\r\n"
5692 "Proxy-Authorization: auth_token\r\n"
5693 "Authorization: auth_token\r\n\r\n");
5694 const MockWrite kConnect(
5695 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5696 "Host: www.example.com\r\n"
5697 "Proxy-Connection: keep-alive\r\n\r\n");
5698 const MockWrite kConnectProxyAuth(
5699 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5700 "Host: www.example.com\r\n"
5701 "Proxy-Connection: keep-alive\r\n"
5702 "Proxy-Authorization: auth_token\r\n\r\n");
5703
5704 const MockRead kSuccess(
5705 "HTTP/1.1 200 OK\r\n"
5706 "Content-Type: text/html; charset=iso-8859-1\r\n"
5707 "Content-Length: 3\r\n\r\n"
5708 "Yes");
5709 const MockRead kFailure(
5710 "Should not be called.");
5711 const MockRead kServerChallenge(
5712 "HTTP/1.1 401 Unauthorized\r\n"
5713 "WWW-Authenticate: Mock realm=server\r\n"
5714 "Content-Type: text/html; charset=iso-8859-1\r\n"
5715 "Content-Length: 14\r\n\r\n"
5716 "Unauthorized\r\n");
5717 const MockRead kProxyChallenge(
5718 "HTTP/1.1 407 Unauthorized\r\n"
5719 "Proxy-Authenticate: Mock realm=proxy\r\n"
5720 "Proxy-Connection: close\r\n"
5721 "Content-Type: text/html; charset=iso-8859-1\r\n"
5722 "Content-Length: 14\r\n\r\n"
5723 "Unauthorized\r\n");
5724 const MockRead kProxyConnected(
5725 "HTTP/1.1 200 Connection Established\r\n\r\n");
5726
5727 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5728 // no constructors, but the C++ compiler on Windows warns about
5729 // unspecified data in compound literals. So, moved to using constructors,
5730 // and TestRound's created with the default constructor should not be used.
5731 struct TestRound {
5732 TestRound()
5733 : expected_rv(ERR_UNEXPECTED),
5734 extra_write(NULL),
5735 extra_read(NULL) {
5736 }
5737 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5738 int expected_rv_arg)
5739 : write(write_arg),
5740 read(read_arg),
5741 expected_rv(expected_rv_arg),
5742 extra_write(NULL),
5743 extra_read(NULL) {
5744 }
5745 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5746 int expected_rv_arg, const MockWrite* extra_write_arg,
5747 const MockWrite* extra_read_arg)
5748 : write(write_arg),
5749 read(read_arg),
5750 expected_rv(expected_rv_arg),
5751 extra_write(extra_write_arg),
5752 extra_read(extra_read_arg) {
5753 }
5754 MockWrite write;
5755 MockRead read;
5756 int expected_rv;
5757 const MockWrite* extra_write;
5758 const MockRead* extra_read;
5759 };
5760
5761 static const int kNoSSL = 500;
5762
5763 struct TestConfig {
5764 const char* proxy_url;
5765 AuthTiming proxy_auth_timing;
5766 int proxy_auth_rv;
5767 const char* server_url;
5768 AuthTiming server_auth_timing;
5769 int server_auth_rv;
5770 int num_auth_rounds;
5771 int first_ssl_round;
5772 TestRound rounds[3];
5773 } test_configs[] = {
5774 // Non-authenticating HTTP server with a direct connection.
5775 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5776 { TestRound(kGet, kSuccess, OK)}},
5777 // Authenticating HTTP server with a direct connection.
5778 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5779 { TestRound(kGet, kServerChallenge, OK),
5780 TestRound(kGetAuth, kSuccess, OK)}},
5781 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5782 { TestRound(kGet, kServerChallenge, OK),
5783 TestRound(kGetAuth, kFailure, kAuthErr)}},
5784 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5785 { TestRound(kGet, kServerChallenge, OK),
5786 TestRound(kGetAuth, kSuccess, OK)}},
5787 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5788 { TestRound(kGet, kServerChallenge, OK),
5789 TestRound(kGetAuth, kFailure, kAuthErr)}},
5790 // Non-authenticating HTTP server through a non-authenticating proxy.
5791 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5792 { TestRound(kGetProxy, kSuccess, OK)}},
5793 // Authenticating HTTP server through a non-authenticating proxy.
5794 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5795 { TestRound(kGetProxy, kServerChallenge, OK),
5796 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5797 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5798 { TestRound(kGetProxy, kServerChallenge, OK),
5799 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5800 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5801 { TestRound(kGetProxy, kServerChallenge, OK),
5802 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5803 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5804 { TestRound(kGetProxy, kServerChallenge, OK),
5805 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5806 // Non-authenticating HTTP server through an authenticating proxy.
5807 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5808 { TestRound(kGetProxy, kProxyChallenge, OK),
5809 TestRound(kGetProxyAuth, kSuccess, OK)}},
5810 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5811 { TestRound(kGetProxy, kProxyChallenge, OK),
5812 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5813 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5814 { TestRound(kGetProxy, kProxyChallenge, OK),
5815 TestRound(kGetProxyAuth, kSuccess, OK)}},
5816 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5817 { TestRound(kGetProxy, kProxyChallenge, OK),
5818 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5819 // Authenticating HTTP server through an authenticating proxy.
5820 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5821 { TestRound(kGetProxy, kProxyChallenge, OK),
5822 TestRound(kGetProxyAuth, kServerChallenge, OK),
5823 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5824 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5825 { TestRound(kGetProxy, kProxyChallenge, OK),
5826 TestRound(kGetProxyAuth, kServerChallenge, OK),
5827 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5828 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5829 { TestRound(kGetProxy, kProxyChallenge, OK),
5830 TestRound(kGetProxyAuth, kServerChallenge, OK),
5831 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5832 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5833 { TestRound(kGetProxy, kProxyChallenge, OK),
5834 TestRound(kGetProxyAuth, kServerChallenge, OK),
5835 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5836 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5837 { TestRound(kGetProxy, kProxyChallenge, OK),
5838 TestRound(kGetProxyAuth, kServerChallenge, OK),
5839 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5840 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5841 { TestRound(kGetProxy, kProxyChallenge, OK),
5842 TestRound(kGetProxyAuth, kServerChallenge, OK),
5843 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5844 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5845 { TestRound(kGetProxy, kProxyChallenge, OK),
5846 TestRound(kGetProxyAuth, kServerChallenge, OK),
5847 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5848 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5849 { TestRound(kGetProxy, kProxyChallenge, OK),
5850 TestRound(kGetProxyAuth, kServerChallenge, OK),
5851 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5852 // Non-authenticating HTTPS server with a direct connection.
5853 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5854 { TestRound(kGet, kSuccess, OK)}},
5855 // Authenticating HTTPS server with a direct connection.
5856 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5857 { TestRound(kGet, kServerChallenge, OK),
5858 TestRound(kGetAuth, kSuccess, OK)}},
5859 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5860 { TestRound(kGet, kServerChallenge, OK),
5861 TestRound(kGetAuth, kFailure, kAuthErr)}},
5862 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5863 { TestRound(kGet, kServerChallenge, OK),
5864 TestRound(kGetAuth, kSuccess, OK)}},
5865 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5866 { TestRound(kGet, kServerChallenge, OK),
5867 TestRound(kGetAuth, kFailure, kAuthErr)}},
5868 // Non-authenticating HTTPS server with a non-authenticating proxy.
5869 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5870 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5871 // Authenticating HTTPS server through a non-authenticating proxy.
5872 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5873 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5874 TestRound(kGetAuth, kSuccess, OK)}},
5875 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5876 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5877 TestRound(kGetAuth, kFailure, kAuthErr)}},
5878 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5879 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5880 TestRound(kGetAuth, kSuccess, OK)}},
5881 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5882 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5883 TestRound(kGetAuth, kFailure, kAuthErr)}},
5884 // Non-Authenticating HTTPS server through an authenticating proxy.
5885 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5886 { TestRound(kConnect, kProxyChallenge, OK),
5887 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5888 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5889 { TestRound(kConnect, kProxyChallenge, OK),
5890 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5891 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5892 { TestRound(kConnect, kProxyChallenge, OK),
5893 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5894 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5895 { TestRound(kConnect, kProxyChallenge, OK),
5896 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5897 // Authenticating HTTPS server through an authenticating proxy.
5898 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5899 { TestRound(kConnect, kProxyChallenge, OK),
5900 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5901 &kGet, &kServerChallenge),
5902 TestRound(kGetAuth, kSuccess, OK)}},
5903 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5904 { TestRound(kConnect, kProxyChallenge, OK),
5905 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5906 &kGet, &kServerChallenge),
5907 TestRound(kGetAuth, kFailure, kAuthErr)}},
5908 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5909 { TestRound(kConnect, kProxyChallenge, OK),
5910 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5911 &kGet, &kServerChallenge),
5912 TestRound(kGetAuth, kSuccess, OK)}},
5913 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5914 { TestRound(kConnect, kProxyChallenge, OK),
5915 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5916 &kGet, &kServerChallenge),
5917 TestRound(kGetAuth, kFailure, kAuthErr)}},
5918 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5919 { TestRound(kConnect, kProxyChallenge, OK),
5920 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5921 &kGet, &kServerChallenge),
5922 TestRound(kGetAuth, kSuccess, OK)}},
5923 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5924 { TestRound(kConnect, kProxyChallenge, OK),
5925 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5926 &kGet, &kServerChallenge),
5927 TestRound(kGetAuth, kFailure, kAuthErr)}},
5928 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5929 { TestRound(kConnect, kProxyChallenge, OK),
5930 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5931 &kGet, &kServerChallenge),
5932 TestRound(kGetAuth, kSuccess, OK)}},
5933 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5934 { TestRound(kConnect, kProxyChallenge, OK),
5935 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5936 &kGet, &kServerChallenge),
5937 TestRound(kGetAuth, kFailure, kAuthErr)}},
5938 };
5939
5940 SessionDependencies session_deps;
5941 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005942 HttpAuthHandlerMock::Factory* auth_factory(
5943 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155944 session_deps.http_auth_handler_factory.reset(auth_factory);
5945
5946 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5947 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:265948
5949 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:155950 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005951 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155952 std::string auth_challenge = "Mock realm=proxy";
5953 GURL origin(test_config.proxy_url);
5954 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5955 auth_challenge.end());
5956 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5957 origin, BoundNetLog());
5958 auth_handler->SetGenerateExpectation(
5959 test_config.proxy_auth_timing == AUTH_ASYNC,
5960 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:155961 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5962 }
5963 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005964 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155965 std::string auth_challenge = "Mock realm=server";
5966 GURL origin(test_config.server_url);
5967 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5968 auth_challenge.end());
5969 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5970 origin, BoundNetLog());
5971 auth_handler->SetGenerateExpectation(
5972 test_config.server_auth_timing == AUTH_ASYNC,
5973 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:155974 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5975 }
5976 if (test_config.proxy_url) {
5977 session_deps.proxy_service =
5978 CreateFixedProxyService(test_config.proxy_url);
5979 } else {
5980 session_deps.proxy_service = ProxyService::CreateNull();
5981 }
5982
5983 HttpRequestInfo request;
5984 request.method = "GET";
5985 request.url = GURL(test_config.server_url);
5986 request.load_flags = 0;
5987
5988 scoped_ptr<HttpTransaction> trans(
5989 new HttpNetworkTransaction(CreateSession(&session_deps)));
5990
5991 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5992 const TestRound& read_write_round = test_config.rounds[round];
5993
5994 // Set up expected reads and writes.
5995 MockRead reads[2];
5996 reads[0] = read_write_round.read;
5997 size_t length_reads = 1;
5998 if (read_write_round.extra_read) {
5999 reads[1] = *read_write_round.extra_read;
6000 length_reads = 2;
6001 }
6002
6003 MockWrite writes[2];
6004 writes[0] = read_write_round.write;
6005 size_t length_writes = 1;
6006 if (read_write_round.extra_write) {
6007 writes[1] = *read_write_round.extra_write;
6008 length_writes = 2;
6009 }
6010 StaticSocketDataProvider data_provider(
6011 reads, length_reads, writes, length_writes);
6012 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6013
6014 // Add an SSL sequence if necessary.
6015 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6016 if (round >= test_config.first_ssl_round)
6017 session_deps.socket_factory.AddSSLSocketDataProvider(
6018 &ssl_socket_data_provider);
6019
6020 // Start or restart the transaction.
6021 TestCompletionCallback callback;
6022 int rv;
6023 if (round == 0) {
6024 rv = trans->Start(&request, &callback, BoundNetLog());
6025 } else {
[email protected]13c8a092010-07-29 06:15:446026 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156027 }
6028 if (rv == ERR_IO_PENDING)
6029 rv = callback.WaitForResult();
6030
6031 // Compare results with expected data.
6032 EXPECT_EQ(read_write_round.expected_rv, rv);
6033 const HttpResponseInfo* response = trans->GetResponseInfo();
6034 if (read_write_round.expected_rv == OK) {
6035 EXPECT_FALSE(response == NULL);
6036 } else {
6037 EXPECT_TRUE(response == NULL);
6038 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6039 continue;
6040 }
6041 if (round + 1 < test_config.num_auth_rounds) {
6042 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6043 } else {
6044 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6045 }
6046 }
[email protected]e5ae96a2010-04-14 20:12:456047 }
[email protected]e60e47a2010-07-14 03:37:186048
6049 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
6050 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:456051}
6052
[email protected]c871bce92010-07-15 21:51:146053TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6054 // Do multi-round authentication and make sure it works correctly.
6055 SessionDependencies session_deps;
6056 HttpAuthHandlerMock::Factory* auth_factory(
6057 new HttpAuthHandlerMock::Factory());
6058 session_deps.http_auth_handler_factory.reset(auth_factory);
6059 session_deps.proxy_service = ProxyService::CreateNull();
6060 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6061 session_deps.host_resolver->set_synchronous_mode(true);
6062
6063 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6064 auth_handler->set_connection_based(true);
6065 std::string auth_challenge = "Mock realm=server";
6066 GURL origin("http://www.example.com");
6067 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6068 auth_challenge.end());
6069 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6070 origin, BoundNetLog());
6071 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6072
6073 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6074 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6075
6076 int rv = OK;
6077 const HttpResponseInfo* response = NULL;
6078 HttpRequestInfo request;
6079 request.method = "GET";
6080 request.url = origin;
6081 request.load_flags = 0;
6082 TestCompletionCallback callback;
6083
6084 const MockWrite kGet(
6085 "GET / HTTP/1.1\r\n"
6086 "Host: www.example.com\r\n"
6087 "Connection: keep-alive\r\n\r\n");
6088 const MockWrite kGetAuth(
6089 "GET / HTTP/1.1\r\n"
6090 "Host: www.example.com\r\n"
6091 "Connection: keep-alive\r\n"
6092 "Authorization: auth_token\r\n\r\n");
6093
6094 const MockRead kServerChallenge(
6095 "HTTP/1.1 401 Unauthorized\r\n"
6096 "WWW-Authenticate: Mock realm=server\r\n"
6097 "Content-Type: text/html; charset=iso-8859-1\r\n"
6098 "Content-Length: 14\r\n\r\n"
6099 "Unauthorized\r\n");
6100 const MockRead kSuccess(
6101 "HTTP/1.1 200 OK\r\n"
6102 "Content-Type: text/html; charset=iso-8859-1\r\n"
6103 "Content-Length: 3\r\n\r\n"
6104 "Yes");
6105
6106 MockWrite writes[] = {
6107 // First round
6108 kGet,
6109 // Second round
6110 kGetAuth,
6111 // Third round
6112 kGetAuth,
6113 };
6114 MockRead reads[] = {
6115 // First round
6116 kServerChallenge,
6117 // Second round
6118 kServerChallenge,
6119 // Third round
6120 kSuccess,
6121 };
6122 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6123 writes, arraysize(writes));
6124 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6125
6126 // First round
6127 auth_handler->SetGenerateExpectation(false, OK);
6128 rv = trans->Start(&request, &callback, BoundNetLog());
6129 if (rv == ERR_IO_PENDING)
6130 rv = callback.WaitForResult();
6131 EXPECT_EQ(OK, rv);
6132 response = trans->GetResponseInfo();
6133 ASSERT_FALSE(response == NULL);
6134 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6135
6136 // Second round
6137 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446138 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146139 if (rv == ERR_IO_PENDING)
6140 rv = callback.WaitForResult();
6141 EXPECT_EQ(OK, rv);
6142 response = trans->GetResponseInfo();
6143 ASSERT_FALSE(response == NULL);
6144 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6145
6146 // Third round
6147 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446148 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146149 if (rv == ERR_IO_PENDING)
6150 rv = callback.WaitForResult();
6151 EXPECT_EQ(OK, rv);
6152 response = trans->GetResponseInfo();
6153 ASSERT_FALSE(response == NULL);
6154 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6155}
6156
[email protected]aeaca1f2010-04-20 22:05:216157class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6158 public:
[email protected]06650c52010-06-03 00:49:176159 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216160 : fail_all_(fail_all) {
6161 }
6162
6163 virtual MockRead GetNextRead() {
6164 if (fail_all_)
6165 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6166
6167 return MockRead(false /* async */,
6168 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6169 }
6170
6171 virtual MockWriteResult OnWrite(const std::string& data) {
6172 return MockWriteResult(false /* async */, data.size());
6173 }
6174
6175 void Reset() {
6176 }
6177
6178 private:
6179 const bool fail_all_;
6180};
6181
6182// Test that we restart a connection when we see a decompression failure from
6183// the peer during the handshake. (In the real world we'll restart with SSLv3
6184// and we won't offer DEFLATE in that case.)
6185TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6186 HttpRequestInfo request;
6187 request.method = "GET";
6188 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6189 request.load_flags = 0;
6190
6191 SessionDependencies session_deps;
6192 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6193 false /* fail all reads */);
6194 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6195 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116196 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216197 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6198 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6199 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6200 session_deps.socket_factory.AddSSLSocketDataProvider(
6201 &ssl_socket_data_provider1);
6202 session_deps.socket_factory.AddSSLSocketDataProvider(
6203 &ssl_socket_data_provider2);
6204
[email protected]e60e47a2010-07-14 03:37:186205 // Work around http://crbug.com/37454
6206 StaticSocketDataProvider bug37454_connection;
6207 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6208 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6209
[email protected]aeaca1f2010-04-20 22:05:216210 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6211 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6212 TestCompletionCallback callback;
6213
[email protected]5a1d7ca2010-04-28 20:12:276214 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216215 EXPECT_EQ(ERR_IO_PENDING, rv);
6216 EXPECT_EQ(OK, callback.WaitForResult());
6217
6218 const HttpResponseInfo* response = trans->GetResponseInfo();
6219 ASSERT_TRUE(response != NULL);
6220 ASSERT_TRUE(response->headers != NULL);
6221 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6222
6223 std::string response_data;
6224 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6225 EXPECT_EQ("ok.", response_data);
6226}
6227
6228// Test that we restart a connection if we get a decompression failure from the
6229// peer while reading the first bytes from the connection. This occurs when the
6230// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6231// in the handshake.
6232TEST_F(HttpNetworkTransactionTest,
6233 RestartAfterTLSDecompressionFailureWithFalseStart) {
6234 HttpRequestInfo request;
6235 request.method = "GET";
6236 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6237 request.load_flags = 0;
6238
6239 SessionDependencies session_deps;
6240 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6241 true /* fail all reads */);
6242 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6243 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6244 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6245 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6246 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6247 session_deps.socket_factory.AddSSLSocketDataProvider(
6248 &ssl_socket_data_provider1);
6249 session_deps.socket_factory.AddSSLSocketDataProvider(
6250 &ssl_socket_data_provider2);
6251
6252 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6253 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6254 TestCompletionCallback callback;
6255
[email protected]5a1d7ca2010-04-28 20:12:276256 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216257 EXPECT_EQ(ERR_IO_PENDING, rv);
6258 EXPECT_EQ(OK, callback.WaitForResult());
6259
6260 const HttpResponseInfo* response = trans->GetResponseInfo();
6261 ASSERT_TRUE(response != NULL);
6262 ASSERT_TRUE(response->headers != NULL);
6263 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6264
6265 std::string response_data;
6266 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6267 EXPECT_EQ("ok.", response_data);
6268}
6269
[email protected]65041fa2010-05-21 06:56:536270// This tests the case that a request is issued via http instead of spdy after
6271// npn is negotiated.
6272TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6273 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6274 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6275 SessionDependencies session_deps;
6276 HttpRequestInfo request;
6277 request.method = "GET";
6278 request.url = GURL("https://www.google.com/");
6279 request.load_flags = 0;
6280
6281 MockWrite data_writes[] = {
6282 MockWrite("GET / HTTP/1.1\r\n"
6283 "Host: www.google.com\r\n"
6284 "Connection: keep-alive\r\n\r\n"),
6285 };
6286
6287 MockRead data_reads[] = {
6288 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356289 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536290 MockRead("hello world"),
6291 MockRead(false, OK),
6292 };
6293
6294 SSLSocketDataProvider ssl(true, OK);
6295 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6296 ssl.next_proto = "http/1.1";
6297
6298 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6299
6300 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6301 data_writes, arraysize(data_writes));
6302 session_deps.socket_factory.AddSocketDataProvider(&data);
6303
6304 TestCompletionCallback callback;
6305
6306 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6307 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6308
6309 int rv = trans->Start(&request, &callback, BoundNetLog());
6310
6311 EXPECT_EQ(ERR_IO_PENDING, rv);
6312 EXPECT_EQ(OK, callback.WaitForResult());
6313
6314 const HttpResponseInfo* response = trans->GetResponseInfo();
6315 ASSERT_TRUE(response != NULL);
6316 ASSERT_TRUE(response->headers != NULL);
6317 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6318
6319 std::string response_data;
6320 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6321 EXPECT_EQ("hello world", response_data);
6322
6323 EXPECT_FALSE(response->was_fetched_via_spdy);
6324 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576325 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536326
6327 HttpNetworkTransaction::SetNextProtos("");
6328 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6329}
[email protected]26ef6582010-06-24 02:30:476330
6331TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6332 // Simulate the SSL handshake completing with an NPN negotiation
6333 // followed by an immediate server closing of the socket.
6334 // Fix crash: http://crbug.com/46369
6335 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:356336 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476337 SessionDependencies session_deps;
6338
6339 HttpRequestInfo request;
6340 request.method = "GET";
6341 request.url = GURL("https://www.google.com/");
6342 request.load_flags = 0;
6343
6344 SSLSocketDataProvider ssl(true, OK);
6345 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356346 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476347 ssl.was_npn_negotiated = true;
6348 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6349
[email protected]2bd93022010-07-17 00:58:446350 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136351 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476352
6353 MockRead spdy_reads[] = {
6354 MockRead(false, 0, 0) // Not async - return 0 immediately.
6355 };
6356
6357 scoped_refptr<DelayedSocketData> spdy_data(
6358 new DelayedSocketData(
6359 0, // don't wait in this case, immediate hangup.
6360 spdy_reads, arraysize(spdy_reads),
6361 spdy_writes, arraysize(spdy_writes)));
6362 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6363
6364 TestCompletionCallback callback;
6365
6366 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6367 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6368
6369 int rv = trans->Start(&request, &callback, BoundNetLog());
6370 EXPECT_EQ(ERR_IO_PENDING, rv);
6371 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6372
6373 HttpNetworkTransaction::SetNextProtos("");
6374 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6375}
[email protected]65d34382010-07-01 18:12:266376
[email protected]f45c1ee2010-08-03 00:54:306377TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
6378 // This test ensures that the URL passed into the proxy is upgraded
6379 // to https when doing an Alternate Protocol upgrade.
6380 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6381 HttpNetworkTransaction::SetNextProtos(
6382 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
6383
6384 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6385 HttpAuthHandlerMock::Factory* auth_factory =
6386 new HttpAuthHandlerMock::Factory();
6387 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
6388 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6389 auth_factory->set_do_init_from_challenge(true);
6390 session_deps.http_auth_handler_factory.reset(auth_factory);
6391
6392 HttpRequestInfo request;
6393 request.method = "GET";
6394 request.url = GURL("http://www.google.com");
6395 request.load_flags = 0;
6396
6397 // First round goes unauthenticated through the proxy.
6398 MockWrite data_writes_1[] = {
6399 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6400 "Host: www.google.com\r\n"
6401 "Proxy-Connection: keep-alive\r\n"
6402 "\r\n"),
6403 };
6404 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:596405 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:306406 MockRead("HTTP/1.1 200 OK\r\n"
6407 "Alternate-Protocol: 443:npn-spdy/2\r\n"
6408 "Proxy-Connection: close\r\n"
6409 "\r\n"),
6410 };
6411 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
6412 data_writes_1, arraysize(data_writes_1));
6413
6414 // Second round tries to tunnel to www.google.com due to the
6415 // Alternate-Protocol announcement in the first round. It fails due
6416 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:596417 // After the failure, a tunnel is established to www.google.com using
6418 // Proxy-Authorization headers. There is then a SPDY request round.
6419 //
6420 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
6421 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
6422 // does a Disconnect and Connect on the same socket, rather than trying
6423 // to obtain a new one.
6424 //
6425 // NOTE: Originally, the proxy response to the second CONNECT request
6426 // simply returned another 407 so the unit test could skip the SSL connection
6427 // establishment and SPDY framing issues. Alas, the
6428 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:306429 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:596430
[email protected]f45c1ee2010-08-03 00:54:306431 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6432 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6433 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6434
[email protected]394816e92010-08-03 07:38:596435 MockWrite data_writes_2[] = {
6436 // First connection attempt without Proxy-Authorization.
6437 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6438 "Host: www.google.com\r\n"
6439 "Proxy-Connection: keep-alive\r\n"
6440 "\r\n"),
6441
6442 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:306443 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6444 "Host: www.google.com\r\n"
6445 "Proxy-Connection: keep-alive\r\n"
6446 "Proxy-Authorization: auth_token\r\n"
6447 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:306448
[email protected]394816e92010-08-03 07:38:596449 // SPDY request
6450 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:306451 };
[email protected]394816e92010-08-03 07:38:596452 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
6453 "Proxy-Authenticate: Mock\r\n"
6454 "Proxy-Connection: close\r\n"
6455 "\r\n");
6456 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6457 MockRead data_reads_2[] = {
6458 // First connection attempt fails
6459 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
6460 MockRead(true, kRejectConnectResponse,
6461 arraysize(kRejectConnectResponse) - 1, 1),
6462
6463 // Second connection attempt passes
6464 MockRead(true, kAcceptConnectResponse,
6465 arraysize(kAcceptConnectResponse) -1, 4),
6466
6467 // SPDY response
6468 CreateMockRead(*resp.get(), 6),
6469 CreateMockRead(*data.get(), 6),
6470 MockRead(true, 0, 0, 6),
6471 };
6472 scoped_refptr<OrderedSocketData> data_2(
6473 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
6474 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:306475
6476 SSLSocketDataProvider ssl(true, OK);
6477 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6478 ssl.next_proto = "spdy/2";
6479 ssl.was_npn_negotiated = true;
6480
6481 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:596482 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:306483 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6484 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6485
6486 // First round should work and provide the Alternate-Protocol state.
6487 TestCompletionCallback callback_1;
6488 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
6489 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
6490 EXPECT_EQ(ERR_IO_PENDING, rv);
6491 EXPECT_EQ(OK, callback_1.WaitForResult());
6492
6493 // Second round should attempt a tunnel connect and get an auth challenge.
6494 TestCompletionCallback callback_2;
6495 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
6496 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
6497 EXPECT_EQ(ERR_IO_PENDING, rv);
6498 EXPECT_EQ(OK, callback_2.WaitForResult());
6499 const HttpResponseInfo* response = trans_2->GetResponseInfo();
6500 ASSERT_FALSE(response == NULL);
6501 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6502
6503 // Restart with auth. Tunnel should work and response received.
6504 TestCompletionCallback callback_3;
6505 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
6506 EXPECT_EQ(ERR_IO_PENDING, rv);
6507 EXPECT_EQ(OK, callback_3.WaitForResult());
6508
6509 // After all that work, these two lines (or actually, just the scheme) are
6510 // what this test is all about. Make sure it happens correctly.
6511 const GURL& request_url = auth_handler->request_url();
6512 EXPECT_EQ("https", request_url.scheme());
6513 EXPECT_EQ("www.google.com", request_url.host());
6514
6515 HttpNetworkTransaction::SetNextProtos("");
6516 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6517}
6518
[email protected]89ceba9a2009-03-21 03:46:066519} // namespace net