blob: dc7c8427e7631cd402cfe0d286246dade61c19f9 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4223#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3324#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/test_completion_callback.h"
26#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1227#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0028#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2929#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5732#include "net/http/http_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5233#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5334#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1135#include "net/proxy/proxy_resolver.h"
36#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4437#include "net/socket/client_socket_factory.h"
38#include "net/socket/socket_test_util.h"
39#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5440#include "net/spdy/spdy_framer.h"
41#include "net/spdy/spdy_session.h"
42#include "net/spdy/spdy_session_pool.h"
43#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5244#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1545#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5246
47//-----------------------------------------------------------------------------
48
[email protected]13c8a092010-07-29 06:15:4449namespace {
50
51const string16 kBar(ASCIIToUTF16("bar"));
52const string16 kBar2(ASCIIToUTF16("bar2"));
53const string16 kBar3(ASCIIToUTF16("bar3"));
54const string16 kBaz(ASCIIToUTF16("baz"));
55const string16 kFirst(ASCIIToUTF16("first"));
56const string16 kFoo(ASCIIToUTF16("foo"));
57const string16 kFoo2(ASCIIToUTF16("foo2"));
58const string16 kFoo3(ASCIIToUTF16("foo3"));
59const string16 kFou(ASCIIToUTF16("fou"));
60const string16 kSecond(ASCIIToUTF16("second"));
61const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
62const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
63
64} // namespace
65
[email protected]89ceba9a2009-03-21 03:46:0666namespace net {
67
[email protected]2d731a32010-04-29 01:04:0668class HttpNetworkSessionPeer {
69 public:
70 explicit HttpNetworkSessionPeer(
71 const scoped_refptr<HttpNetworkSession>& session)
72 : session_(session) {}
73
74 void SetTCPSocketPool(const scoped_refptr<TCPClientSocketPool>& pool) {
75 session_->tcp_socket_pool_ = pool;
76 }
77
78 void SetSocketPoolForSOCKSProxy(
79 const HostPortPair& socks_proxy,
80 const scoped_refptr<SOCKSClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1881 session_->socks_socket_pools_[socks_proxy] = pool;
[email protected]2d731a32010-04-29 01:04:0682 }
83
84 void SetSocketPoolForHTTPProxy(
85 const HostPortPair& http_proxy,
[email protected]e772db3f2010-07-12 18:11:1386 const scoped_refptr<HttpProxyClientSocketPool>& pool) {
[email protected]e60e47a2010-07-14 03:37:1887 session_->http_proxy_socket_pools_[http_proxy] = pool;
88 }
89
90 void SetSSLSocketPool(const scoped_refptr<SSLClientSocketPool>& pool) {
91 session_->ssl_socket_pool_ = pool;
92 }
93
94 void SetSocketPoolForSSLWithProxy(
95 const HostPortPair& proxy_host,
96 const scoped_refptr<SSLClientSocketPool>& pool) {
97 session_->ssl_socket_pools_for_proxies_[proxy_host] = pool;
[email protected]2d731a32010-04-29 01:04:0698 }
99
100 private:
101 const scoped_refptr<HttpNetworkSession> session_;
102
103 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
104};
105
[email protected]e44de5d2009-06-05 20:12:45106// Helper to manage the lifetimes of the dependencies for a
107// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44108struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59109 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42110 SessionDependencies()
111 : host_resolver(new MockHostResolver),
[email protected]dded3e22010-02-05 04:08:37112 proxy_service(ProxyService::CreateNull()),
[email protected]d1eda932009-11-04 01:03:10113 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52114 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54115 spdy_session_pool(new SpdySessionPool()),
116 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59117
118 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45119 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42120 : host_resolver(new MockHostResolver),
121 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10122 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]a554a8262010-05-20 00:13:52123 http_auth_handler_factory(HttpAuthHandlerFactory::CreateDefault()),
[email protected]a7ea8832010-07-12 17:54:54124 spdy_session_pool(new SpdySessionPool()),
125 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59126
[email protected]a2c2fb92009-07-18 07:31:04127 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:09128 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42129 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59130 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50131 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52132 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]a7ea8832010-07-12 17:54:54133 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59134};
135
[email protected]1c773ea12009-04-28 19:58:42136ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50137 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48138 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39139 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53140}
141
[email protected]228ff742009-06-05 01:19:59142HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38143 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09144 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42145 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10146 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52147 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17148 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44149 NULL,
[email protected]a7ea8832010-07-12 17:54:54150 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14151}
152
[email protected]89836e22008-09-25 20:33:42153class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52154 public:
[email protected]2ff8b312010-04-26 22:20:54155 virtual void SetUp() {
156 spdy::SpdyFramer::set_enable_compression_default(false);
157 }
158
[email protected]0e75a732008-10-16 20:36:09159 virtual void TearDown() {
[email protected]2ff8b312010-04-26 22:20:54160 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09161 // Empty the current queue.
162 MessageLoop::current()->RunAllPending();
163 PlatformTest::TearDown();
164 }
165
[email protected]3d2a59b2008-09-26 19:44:25166 protected:
167 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52168
[email protected]ff007e162009-05-23 09:13:15169 struct SimpleGetHelperResult {
170 int rv;
171 std::string status_line;
172 std::string response_data;
173 };
initial.commit586acc5fe2008-07-26 22:42:52174
[email protected]31a2bfe2010-02-09 08:03:39175 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
176 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15177 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52178
[email protected]228ff742009-06-05 01:19:59179 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40180 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43181 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52182
[email protected]ff007e162009-05-23 09:13:15183 HttpRequestInfo request;
184 request.method = "GET";
185 request.url = GURL("http://www.google.com/");
186 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52187
[email protected]31a2bfe2010-02-09 08:03:39188 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59189 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52190
[email protected]ff007e162009-05-23 09:13:15191 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52192
[email protected]169d0012010-05-10 23:20:12193 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
194 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15195 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52196
[email protected]ff007e162009-05-23 09:13:15197 out.rv = callback.WaitForResult();
198 if (out.rv != OK)
199 return out;
200
201 const HttpResponseInfo* response = trans->GetResponseInfo();
202 EXPECT_TRUE(response != NULL);
203
204 EXPECT_TRUE(response->headers != NULL);
205 out.status_line = response->headers->GetStatusLine();
206
207 rv = ReadTransaction(trans.get(), &out.response_data);
208 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39209 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12210 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
211 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39212 ExpectLogContainsSomewhere(
213 log.entries(), pos,
214 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
215 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15216
[email protected]aecfbf22008-10-16 02:02:47217 return out;
[email protected]ff007e162009-05-23 09:13:15218 }
initial.commit586acc5fe2008-07-26 22:42:52219
[email protected]ff007e162009-05-23 09:13:15220 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
221 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52222
[email protected]ff007e162009-05-23 09:13:15223 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15224};
[email protected]231d5a32008-09-13 00:45:27225
[email protected]15a5ccf82008-10-23 19:57:43226// Fill |str| with a long header list that consumes >= |size| bytes.
227void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19228 const char* row =
229 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
230 const int sizeof_row = strlen(row);
231 const int num_rows = static_cast<int>(
232 ceil(static_cast<float>(size) / sizeof_row));
233 const int sizeof_data = num_rows * sizeof_row;
234 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43235 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51236
[email protected]4ddaf2502008-10-23 18:26:19237 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43238 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19239}
240
[email protected]385a4672009-03-11 22:21:29241// Alternative functions that eliminate randomness and dependency on the local
242// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20243void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29244 static const uint8 bytes[] = {
245 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
246 };
247 static size_t current_byte = 0;
248 for (size_t i = 0; i < n; ++i) {
249 output[i] = bytes[current_byte++];
250 current_byte %= arraysize(bytes);
251 }
252}
253
[email protected]fe2bc6a2009-03-23 16:52:20254void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29255 static const uint8 bytes[] = {
256 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
257 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
258 };
259 static size_t current_byte = 0;
260 for (size_t i = 0; i < n; ++i) {
261 output[i] = bytes[current_byte++];
262 current_byte %= arraysize(bytes);
263 }
264}
265
[email protected]fe2bc6a2009-03-23 16:52:20266std::string MockGetHostName() {
267 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29268}
269
[email protected]e60e47a2010-07-14 03:37:18270template<typename ParentPool>
271class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31272 public:
[email protected]e60e47a2010-07-14 03:37:18273 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
274
[email protected]d80a4322009-08-14 07:07:49275 const std::string last_group_name_received() const {
276 return last_group_name_;
277 }
278
[email protected]684970b2009-08-14 04:54:46279 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49280 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31281 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31282 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46283 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53284 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31285 last_group_name_ = group_name;
286 return ERR_IO_PENDING;
287 }
[email protected]04e5be32009-06-26 20:00:31288 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21289 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31290 virtual void ReleaseSocket(const std::string& group_name,
291 ClientSocket* socket) {}
292 virtual void CloseIdleSockets() {}
293 virtual HostResolver* GetHostResolver() const {
294 return NULL;
295 }
296 virtual int IdleSocketCount() const {
297 return 0;
298 }
299 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
300 return 0;
301 }
302 virtual LoadState GetLoadState(const std::string& group_name,
303 const ClientSocketHandle* handle) const {
304 return LOAD_STATE_IDLE;
305 }
[email protected]a796bcec2010-03-22 17:17:26306 virtual base::TimeDelta ConnectionTimeout() const {
307 return base::TimeDelta();
308 }
[email protected]d80a4322009-08-14 07:07:49309
310 private:
[email protected]04e5be32009-06-26 20:00:31311 std::string last_group_name_;
312};
313
[email protected]2d731a32010-04-29 01:04:06314typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11315CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13316typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
317CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06318typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11319CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18320typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
321CaptureGroupNameSSLSocketPool;
322
323template<typename ParentPool>
324CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
325 HttpNetworkSession* session)
326 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
327
328template<>
329CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
330 HttpNetworkSession* session)
331 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
332 NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11333
[email protected]231d5a32008-09-13 00:45:27334//-----------------------------------------------------------------------------
335
[email protected]dae22c52010-07-30 02:16:35336// This is the expected list of advertised protocols from the browser's NPN
337// list.
338static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
339
340// This is the expected return from a current server advertising SPDY.
341static const char kAlternateProtocolHttpHeader[] =
342 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
343
[email protected]231d5a32008-09-13 00:45:27344TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59345 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40346 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43347 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27348}
349
350TEST_F(HttpNetworkTransactionTest, SimpleGET) {
351 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35352 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
353 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42354 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27355 };
[email protected]31a2bfe2010-02-09 08:03:39356 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
357 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42358 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27359 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
360 EXPECT_EQ("hello world", out.response_data);
361}
362
363// Response with no status line.
364TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
365 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35366 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42367 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27368 };
[email protected]31a2bfe2010-02-09 08:03:39369 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
370 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42371 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27372 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
373 EXPECT_EQ("hello world", out.response_data);
374}
375
376// Allow up to 4 bytes of junk to precede status line.
377TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
378 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35379 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42380 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27381 };
[email protected]31a2bfe2010-02-09 08:03:39382 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
383 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42384 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27385 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
386 EXPECT_EQ("DATA", out.response_data);
387}
388
389// Allow up to 4 bytes of junk to precede status line.
390TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
391 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35392 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42393 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27394 };
[email protected]31a2bfe2010-02-09 08:03:39395 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
396 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42397 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27398 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
399 EXPECT_EQ("DATA", out.response_data);
400}
401
402// Beyond 4 bytes of slop and it should fail to find a status line.
403TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
404 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35405 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42406 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27407 };
[email protected]31a2bfe2010-02-09 08:03:39408 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
409 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42410 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25411 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
412 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27413}
414
415// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
416TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
417 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35418 MockRead("\n"),
419 MockRead("\n"),
420 MockRead("Q"),
421 MockRead("J"),
422 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42423 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27424 };
[email protected]31a2bfe2010-02-09 08:03:39425 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
426 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42427 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27428 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
429 EXPECT_EQ("DATA", out.response_data);
430}
431
432// Close the connection before enough bytes to have a status line.
433TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
434 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35435 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42436 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27437 };
[email protected]31a2bfe2010-02-09 08:03:39438 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
439 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42440 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27441 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
442 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52443}
444
[email protected]f9d44aa2008-09-23 23:57:17445// Simulate a 204 response, lacking a Content-Length header, sent over a
446// persistent connection. The response should still terminate since a 204
447// cannot have a response body.
448TEST_F(HttpNetworkTransactionTest, StopsReading204) {
449 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35450 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
451 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42452 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17453 };
[email protected]31a2bfe2010-02-09 08:03:39454 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
455 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42456 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17457 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
458 EXPECT_EQ("", out.response_data);
459}
460
[email protected]0877e3d2009-10-17 22:29:57461// A simple request using chunked encoding with some extra data after.
462// (Like might be seen in a pipelined response.)
463TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
464 MockRead data_reads[] = {
465 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
466 MockRead("5\r\nHello\r\n"),
467 MockRead("1\r\n"),
468 MockRead(" \r\n"),
469 MockRead("5\r\nworld\r\n"),
470 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
471 MockRead(false, OK),
472 };
[email protected]31a2bfe2010-02-09 08:03:39473 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
474 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57475 EXPECT_EQ(OK, out.rv);
476 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
477 EXPECT_EQ("Hello world", out.response_data);
478}
479
[email protected]ef0faf2e72009-03-05 23:27:23480// Do a request using the HEAD method. Verify that we don't try to read the
481// message body (since HEAD has none).
482TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59483 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40484 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43485 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23486
[email protected]1c773ea12009-04-28 19:58:42487 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23488 request.method = "HEAD";
489 request.url = GURL("http://www.google.com/");
490 request.load_flags = 0;
491
492 MockWrite data_writes1[] = {
493 MockWrite("HEAD / HTTP/1.1\r\n"
494 "Host: www.google.com\r\n"
495 "Connection: keep-alive\r\n"
496 "Content-Length: 0\r\n\r\n"),
497 };
498 MockRead data_reads1[] = {
499 MockRead("HTTP/1.1 404 Not Found\r\n"),
500 MockRead("Server: Blah\r\n"),
501 MockRead("Content-Length: 1234\r\n\r\n"),
502
503 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42504 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23505 };
506
[email protected]31a2bfe2010-02-09 08:03:39507 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
508 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59509 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23510
511 TestCompletionCallback callback1;
512
[email protected]5a1d7ca2010-04-28 20:12:27513 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42514 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23515
516 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42517 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23518
[email protected]1c773ea12009-04-28 19:58:42519 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23520 EXPECT_FALSE(response == NULL);
521
522 // Check that the headers got parsed.
523 EXPECT_TRUE(response->headers != NULL);
524 EXPECT_EQ(1234, response->headers->GetContentLength());
525 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
526
527 std::string server_header;
528 void* iter = NULL;
529 bool has_server_header = response->headers->EnumerateHeader(
530 &iter, "Server", &server_header);
531 EXPECT_TRUE(has_server_header);
532 EXPECT_EQ("Blah", server_header);
533
534 // Reading should give EOF right away, since there is no message body
535 // (despite non-zero content-length).
536 std::string response_data;
537 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42538 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23539 EXPECT_EQ("", response_data);
540}
541
initial.commit586acc5fe2008-07-26 22:42:52542TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59543 SessionDependencies session_deps;
544 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52545
546 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35547 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
548 MockRead("hello"),
549 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
550 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42551 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52552 };
[email protected]31a2bfe2010-02-09 08:03:39553 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59554 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52555
556 const char* kExpectedResponseData[] = {
557 "hello", "world"
558 };
559
560 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43561 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52562
[email protected]1c773ea12009-04-28 19:58:42563 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52564 request.method = "GET";
565 request.url = GURL("http://www.google.com/");
566 request.load_flags = 0;
567
568 TestCompletionCallback callback;
569
[email protected]5a1d7ca2010-04-28 20:12:27570 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42571 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52572
573 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42574 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52575
[email protected]1c773ea12009-04-28 19:58:42576 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52577 EXPECT_TRUE(response != NULL);
578
579 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25580 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52581
582 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57583 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42584 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25585 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52586 }
587}
588
589TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59590 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40591 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43592 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52593
[email protected]1c773ea12009-04-28 19:58:42594 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52595 request.method = "POST";
596 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42597 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52598 request.upload_data->AppendBytes("foo", 3);
599 request.load_flags = 0;
600
601 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35602 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
603 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
604 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42605 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52606 };
[email protected]31a2bfe2010-02-09 08:03:39607 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59608 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52609
610 TestCompletionCallback callback;
611
[email protected]5a1d7ca2010-04-28 20:12:27612 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42613 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52614
615 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42616 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52617
[email protected]1c773ea12009-04-28 19:58:42618 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52619 EXPECT_TRUE(response != NULL);
620
621 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25622 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52623
624 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57625 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42626 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25627 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52628}
629
[email protected]3a2d3662009-03-27 03:49:14630// This test is almost the same as Ignores100 above, but the response contains
631// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57632// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14633TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59634 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40635 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43636 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14637
[email protected]1c773ea12009-04-28 19:58:42638 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14639 request.method = "GET";
640 request.url = GURL("http://www.foo.com/");
641 request.load_flags = 0;
642
643 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57644 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
645 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14646 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42647 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14648 };
[email protected]31a2bfe2010-02-09 08:03:39649 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59650 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14651
652 TestCompletionCallback callback;
653
[email protected]5a1d7ca2010-04-28 20:12:27654 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42655 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14656
657 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42658 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14659
[email protected]1c773ea12009-04-28 19:58:42660 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14661 EXPECT_TRUE(response != NULL);
662
663 EXPECT_TRUE(response->headers != NULL);
664 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
665
666 std::string response_data;
667 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42668 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14669 EXPECT_EQ("hello world", response_data);
670}
671
[email protected]ee9410e72010-01-07 01:42:38672TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
673 SessionDependencies session_deps;
674 scoped_ptr<HttpTransaction> trans(
675 new HttpNetworkTransaction(CreateSession(&session_deps)));
676
677 HttpRequestInfo request;
678 request.method = "POST";
679 request.url = GURL("http://www.foo.com/");
680 request.load_flags = 0;
681
682 MockRead data_reads[] = {
683 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
684 MockRead(true, 0),
685 };
[email protected]31a2bfe2010-02-09 08:03:39686 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38687 session_deps.socket_factory.AddSocketDataProvider(&data);
688
689 TestCompletionCallback callback;
690
[email protected]5a1d7ca2010-04-28 20:12:27691 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38692 EXPECT_EQ(ERR_IO_PENDING, rv);
693
694 rv = callback.WaitForResult();
695 EXPECT_EQ(OK, rv);
696
697 std::string response_data;
698 rv = ReadTransaction(trans.get(), &response_data);
699 EXPECT_EQ(OK, rv);
700 EXPECT_EQ("", response_data);
701}
702
703TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
704 SessionDependencies session_deps;
705 scoped_ptr<HttpTransaction> trans(
706 new HttpNetworkTransaction(CreateSession(&session_deps)));
707
708 HttpRequestInfo request;
709 request.method = "POST";
710 request.url = GURL("http://www.foo.com/");
711 request.load_flags = 0;
712
713 MockRead data_reads[] = {
714 MockRead(true, 0),
715 };
[email protected]31a2bfe2010-02-09 08:03:39716 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38717 session_deps.socket_factory.AddSocketDataProvider(&data);
718
719 TestCompletionCallback callback;
720
[email protected]5a1d7ca2010-04-28 20:12:27721 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38722 EXPECT_EQ(ERR_IO_PENDING, rv);
723
724 rv = callback.WaitForResult();
725 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
726}
727
[email protected]3d2a59b2008-09-26 19:44:25728// read_failure specifies a read failure that should cause the network
729// transaction to resend the request.
730void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
731 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59732 SessionDependencies session_deps;
733 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52734
[email protected]1c773ea12009-04-28 19:58:42735 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52736 request.method = "GET";
737 request.url = GURL("http://www.foo.com/");
738 request.load_flags = 0;
739
740 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35741 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
742 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25743 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52744 };
[email protected]31a2bfe2010-02-09 08:03:39745 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59746 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52747
748 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35749 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
750 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42751 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52752 };
[email protected]31a2bfe2010-02-09 08:03:39753 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59754 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52755
756 const char* kExpectedResponseData[] = {
757 "hello", "world"
758 };
759
760 for (int i = 0; i < 2; ++i) {
761 TestCompletionCallback callback;
762
[email protected]5695b8c2009-09-30 21:36:43763 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52764
[email protected]5a1d7ca2010-04-28 20:12:27765 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42766 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52767
768 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42769 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52770
[email protected]1c773ea12009-04-28 19:58:42771 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52772 EXPECT_TRUE(response != NULL);
773
774 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25775 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52776
777 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57778 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42779 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25780 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52781 }
782}
[email protected]3d2a59b2008-09-26 19:44:25783
784TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42785 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25786 KeepAliveConnectionResendRequestTest(read_failure);
787}
788
789TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42790 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25791 KeepAliveConnectionResendRequestTest(read_failure);
792}
793
794TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59795 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40796 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43797 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25798
[email protected]1c773ea12009-04-28 19:58:42799 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25800 request.method = "GET";
801 request.url = GURL("http://www.google.com/");
802 request.load_flags = 0;
803
804 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42805 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35806 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
807 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42808 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25809 };
[email protected]31a2bfe2010-02-09 08:03:39810 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59811 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25812
813 TestCompletionCallback callback;
814
[email protected]5a1d7ca2010-04-28 20:12:27815 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42816 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25817
818 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42819 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25820
[email protected]1c773ea12009-04-28 19:58:42821 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25822 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25823}
824
825// What do various browsers do when the server closes a non-keepalive
826// connection without sending any response header or body?
827//
828// IE7: error page
829// Safari 3.1.2 (Windows): error page
830// Firefox 3.0.1: blank page
831// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42832// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
833// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25834TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
835 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42836 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35837 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
838 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42839 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25840 };
[email protected]31a2bfe2010-02-09 08:03:39841 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
842 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42843 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25844}
[email protected]038e9a32008-10-08 22:40:16845
[email protected]fc31d6a42010-06-24 18:05:13846// Test that we correctly reuse a keep-alive connection after receiving a 304.
847TEST_F(HttpNetworkTransactionTest, KeepAliveAfter304) {
848 SessionDependencies session_deps;
849 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
850
851 HttpRequestInfo request;
852 request.method = "GET";
853 request.url = GURL("http://www.foo.com/");
854 request.load_flags = 0;
855
856 MockRead data1_reads[] = {
857 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
858 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
859 MockRead("hello"),
860 };
861 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
862 session_deps.socket_factory.AddSocketDataProvider(&data1);
863
864 MockRead data2_reads[] = {
865 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
866 };
867 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
868 session_deps.socket_factory.AddSocketDataProvider(&data2);
869
870 for (int i = 0; i < 2; ++i) {
871 TestCompletionCallback callback;
872
873 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
874
875 int rv = trans->Start(&request, &callback, BoundNetLog());
876 EXPECT_EQ(ERR_IO_PENDING, rv);
877
878 rv = callback.WaitForResult();
879 EXPECT_EQ(OK, rv);
880
881 const HttpResponseInfo* response = trans->GetResponseInfo();
882 EXPECT_TRUE(response != NULL);
883
884 EXPECT_TRUE(response->headers != NULL);
885 if (i == 0) {
886 EXPECT_EQ("HTTP/1.1 304 Not Modified",
887 response->headers->GetStatusLine());
888 // We intentionally don't read the response in this case, to reflect how
889 // HttpCache::Transaction uses HttpNetworkTransaction.
890 } else {
891 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
892 std::string response_data;
893 rv = ReadTransaction(trans.get(), &response_data);
894 EXPECT_EQ(OK, rv);
895 EXPECT_EQ("hello", response_data);
896 }
897 }
898}
899
[email protected]038e9a32008-10-08 22:40:16900// Test the request-challenge-retry sequence for basic auth.
901// (basic auth is the easiest to mock, because it has no randomness).
902TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:59903 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40904 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43905 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:16906
[email protected]1c773ea12009-04-28 19:58:42907 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:16908 request.method = "GET";
909 request.url = GURL("http://www.google.com/");
910 request.load_flags = 0;
911
[email protected]f9ee6b52008-11-08 06:46:23912 MockWrite data_writes1[] = {
913 MockWrite("GET / HTTP/1.1\r\n"
914 "Host: www.google.com\r\n"
915 "Connection: keep-alive\r\n\r\n"),
916 };
917
[email protected]038e9a32008-10-08 22:40:16918 MockRead data_reads1[] = {
919 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
920 // Give a couple authenticate options (only the middle one is actually
921 // supported).
[email protected]22927ad2009-09-21 19:56:19922 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:16923 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
924 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
925 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
926 // Large content-length -- won't matter, as connection will be reset.
927 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42928 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:16929 };
930
931 // After calling trans->RestartWithAuth(), this is the request we should
932 // be issuing -- the final header line contains the credentials.
933 MockWrite data_writes2[] = {
934 MockWrite("GET / HTTP/1.1\r\n"
935 "Host: www.google.com\r\n"
936 "Connection: keep-alive\r\n"
937 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
938 };
939
940 // Lastly, the server responds with the actual content.
941 MockRead data_reads2[] = {
942 MockRead("HTTP/1.0 200 OK\r\n"),
943 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
944 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:42945 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:16946 };
947
[email protected]31a2bfe2010-02-09 08:03:39948 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
949 data_writes1, arraysize(data_writes1));
950 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
951 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:59952 session_deps.socket_factory.AddSocketDataProvider(&data1);
953 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:16954
955 TestCompletionCallback callback1;
956
[email protected]5a1d7ca2010-04-28 20:12:27957 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42958 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16959
960 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42961 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16962
[email protected]1c773ea12009-04-28 19:58:42963 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:16964 EXPECT_FALSE(response == NULL);
965
966 // The password prompt info should have been set in response->auth_challenge.
967 EXPECT_FALSE(response->auth_challenge.get() == NULL);
968
[email protected]71e4573a2009-05-21 22:03:00969 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:16970 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
971 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
972
973 TestCompletionCallback callback2;
974
[email protected]13c8a092010-07-29 06:15:44975 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:42976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:16977
978 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42979 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:16980
981 response = trans->GetResponseInfo();
982 EXPECT_FALSE(response == NULL);
983 EXPECT_TRUE(response->auth_challenge.get() == NULL);
984 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:16985}
986
[email protected]861fcd52009-08-26 02:33:46987TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
988 SessionDependencies session_deps;
989 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43990 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:46991
992 HttpRequestInfo request;
993 request.method = "GET";
994 request.url = GURL("http://www.google.com/");
995 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
996
997 MockWrite data_writes[] = {
998 MockWrite("GET / HTTP/1.1\r\n"
999 "Host: www.google.com\r\n"
1000 "Connection: keep-alive\r\n\r\n"),
1001 };
1002
1003 MockRead data_reads[] = {
1004 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1005 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1006 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1007 // Large content-length -- won't matter, as connection will be reset.
1008 MockRead("Content-Length: 10000\r\n\r\n"),
1009 MockRead(false, ERR_FAILED),
1010 };
1011
[email protected]31a2bfe2010-02-09 08:03:391012 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1013 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591014 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461015 TestCompletionCallback callback;
1016
[email protected]5a1d7ca2010-04-28 20:12:271017 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461018 EXPECT_EQ(ERR_IO_PENDING, rv);
1019
1020 rv = callback.WaitForResult();
1021 EXPECT_EQ(0, rv);
1022
1023 const HttpResponseInfo* response = trans->GetResponseInfo();
1024 ASSERT_FALSE(response == NULL);
1025 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1026}
1027
[email protected]2d2697f92009-02-18 21:00:321028// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1029// connection.
1030TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591031 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401032 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431033 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321034
[email protected]1c773ea12009-04-28 19:58:421035 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321036 request.method = "GET";
1037 request.url = GURL("http://www.google.com/");
1038 request.load_flags = 0;
1039
1040 MockWrite data_writes1[] = {
1041 MockWrite("GET / HTTP/1.1\r\n"
1042 "Host: www.google.com\r\n"
1043 "Connection: keep-alive\r\n\r\n"),
1044
1045 // After calling trans->RestartWithAuth(), this is the request we should
1046 // be issuing -- the final header line contains the credentials.
1047 MockWrite("GET / HTTP/1.1\r\n"
1048 "Host: www.google.com\r\n"
1049 "Connection: keep-alive\r\n"
1050 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1051 };
1052
1053 MockRead data_reads1[] = {
1054 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1055 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1056 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1057 MockRead("Content-Length: 14\r\n\r\n"),
1058 MockRead("Unauthorized\r\n"),
1059
1060 // Lastly, the server responds with the actual content.
1061 MockRead("HTTP/1.1 200 OK\r\n"),
1062 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1063 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421064 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321065 };
1066
[email protected]31a2bfe2010-02-09 08:03:391067 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1068 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591069 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321070
1071 TestCompletionCallback callback1;
1072
[email protected]5a1d7ca2010-04-28 20:12:271073 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421074 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321075
1076 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421077 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321078
[email protected]1c773ea12009-04-28 19:58:421079 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321080 EXPECT_FALSE(response == NULL);
1081
1082 // The password prompt info should have been set in response->auth_challenge.
1083 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1084
[email protected]71e4573a2009-05-21 22:03:001085 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321086 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1087 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1088
1089 TestCompletionCallback callback2;
1090
[email protected]13c8a092010-07-29 06:15:441091 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421092 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321093
1094 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421095 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321096
1097 response = trans->GetResponseInfo();
1098 EXPECT_FALSE(response == NULL);
1099 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1100 EXPECT_EQ(100, response->headers->GetContentLength());
1101}
1102
1103// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1104// connection and with no response body to drain.
1105TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591106 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401107 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431108 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321109
[email protected]1c773ea12009-04-28 19:58:421110 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321111 request.method = "GET";
1112 request.url = GURL("http://www.google.com/");
1113 request.load_flags = 0;
1114
1115 MockWrite data_writes1[] = {
1116 MockWrite("GET / HTTP/1.1\r\n"
1117 "Host: www.google.com\r\n"
1118 "Connection: keep-alive\r\n\r\n"),
1119
1120 // After calling trans->RestartWithAuth(), this is the request we should
1121 // be issuing -- the final header line contains the credentials.
1122 MockWrite("GET / HTTP/1.1\r\n"
1123 "Host: www.google.com\r\n"
1124 "Connection: keep-alive\r\n"
1125 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1126 };
1127
[email protected]2d2697f92009-02-18 21:00:321128 MockRead data_reads1[] = {
1129 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1130 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311131 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321132
1133 // Lastly, the server responds with the actual content.
1134 MockRead("HTTP/1.1 200 OK\r\n"),
1135 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1136 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421137 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321138 };
1139
[email protected]31a2bfe2010-02-09 08:03:391140 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1141 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591142 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321143
1144 TestCompletionCallback callback1;
1145
[email protected]5a1d7ca2010-04-28 20:12:271146 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421147 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321148
1149 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421150 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321151
[email protected]1c773ea12009-04-28 19:58:421152 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321153 EXPECT_FALSE(response == NULL);
1154
1155 // The password prompt info should have been set in response->auth_challenge.
1156 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1157
[email protected]71e4573a2009-05-21 22:03:001158 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321159 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1160 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1161
1162 TestCompletionCallback callback2;
1163
[email protected]13c8a092010-07-29 06:15:441164 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421165 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321166
1167 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421168 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321169
1170 response = trans->GetResponseInfo();
1171 EXPECT_FALSE(response == NULL);
1172 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1173 EXPECT_EQ(100, response->headers->GetContentLength());
1174}
1175
1176// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1177// connection and with a large response body to drain.
1178TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591179 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401180 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431181 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]2d2697f92009-02-18 21:00:321182
[email protected]1c773ea12009-04-28 19:58:421183 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321184 request.method = "GET";
1185 request.url = GURL("http://www.google.com/");
1186 request.load_flags = 0;
1187
1188 MockWrite data_writes1[] = {
1189 MockWrite("GET / HTTP/1.1\r\n"
1190 "Host: www.google.com\r\n"
1191 "Connection: keep-alive\r\n\r\n"),
1192
1193 // After calling trans->RestartWithAuth(), this is the request we should
1194 // be issuing -- the final header line contains the credentials.
1195 MockWrite("GET / HTTP/1.1\r\n"
1196 "Host: www.google.com\r\n"
1197 "Connection: keep-alive\r\n"
1198 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1199 };
1200
1201 // Respond with 5 kb of response body.
1202 std::string large_body_string("Unauthorized");
1203 large_body_string.append(5 * 1024, ' ');
1204 large_body_string.append("\r\n");
1205
1206 MockRead data_reads1[] = {
1207 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1208 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1209 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1210 // 5134 = 12 + 5 * 1024 + 2
1211 MockRead("Content-Length: 5134\r\n\r\n"),
1212 MockRead(true, large_body_string.data(), large_body_string.size()),
1213
1214 // Lastly, the server responds with the actual content.
1215 MockRead("HTTP/1.1 200 OK\r\n"),
1216 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1217 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421218 MockRead(false, OK),
[email protected]2d2697f92009-02-18 21:00:321219 };
1220
[email protected]31a2bfe2010-02-09 08:03:391221 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1222 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591223 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321224
1225 TestCompletionCallback callback1;
1226
[email protected]5a1d7ca2010-04-28 20:12:271227 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421228 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321229
1230 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421231 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321232
[email protected]1c773ea12009-04-28 19:58:421233 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321234 EXPECT_FALSE(response == NULL);
1235
1236 // The password prompt info should have been set in response->auth_challenge.
1237 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1238
[email protected]71e4573a2009-05-21 22:03:001239 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321240 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1241 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1242
1243 TestCompletionCallback callback2;
1244
[email protected]13c8a092010-07-29 06:15:441245 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421246 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321247
1248 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421249 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321250
1251 response = trans->GetResponseInfo();
1252 EXPECT_FALSE(response == NULL);
1253 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1254 EXPECT_EQ(100, response->headers->GetContentLength());
1255}
1256
1257// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311258// connection, but the server gets impatient and closes the connection.
1259TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1260 SessionDependencies session_deps;
1261 scoped_ptr<HttpTransaction> trans(
1262 new HttpNetworkTransaction(CreateSession(&session_deps)));
1263
1264 HttpRequestInfo request;
1265 request.method = "GET";
1266 request.url = GURL("http://www.google.com/");
1267 request.load_flags = 0;
1268
1269 MockWrite data_writes1[] = {
1270 MockWrite("GET / HTTP/1.1\r\n"
1271 "Host: www.google.com\r\n"
1272 "Connection: keep-alive\r\n\r\n"),
1273 // This simulates the seemingly successful write to a closed connection
1274 // if the bug is not fixed.
1275 MockWrite("GET / HTTP/1.1\r\n"
1276 "Host: www.google.com\r\n"
1277 "Connection: keep-alive\r\n"
1278 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1279 };
1280
1281 MockRead data_reads1[] = {
1282 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1283 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1285 MockRead("Content-Length: 14\r\n\r\n"),
1286 // Tell MockTCPClientSocket to simulate the server closing the connection.
1287 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1288 MockRead("Unauthorized\r\n"),
1289 MockRead(false, OK), // The server closes the connection.
1290 };
1291
1292 // After calling trans->RestartWithAuth(), this is the request we should
1293 // be issuing -- the final header line contains the credentials.
1294 MockWrite data_writes2[] = {
1295 MockWrite("GET / HTTP/1.1\r\n"
1296 "Host: www.google.com\r\n"
1297 "Connection: keep-alive\r\n"
1298 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1299 };
1300
1301 // Lastly, the server responds with the actual content.
1302 MockRead data_reads2[] = {
1303 MockRead("HTTP/1.1 200 OK\r\n"),
1304 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1305 MockRead("Content-Length: 100\r\n\r\n"),
1306 MockRead(false, OK),
1307 };
1308
[email protected]31a2bfe2010-02-09 08:03:391309 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1310 data_writes1, arraysize(data_writes1));
1311 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1312 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311313 session_deps.socket_factory.AddSocketDataProvider(&data1);
1314 session_deps.socket_factory.AddSocketDataProvider(&data2);
1315
1316 TestCompletionCallback callback1;
1317
[email protected]5a1d7ca2010-04-28 20:12:271318 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311319 EXPECT_EQ(ERR_IO_PENDING, rv);
1320
1321 rv = callback1.WaitForResult();
1322 EXPECT_EQ(OK, rv);
1323
1324 const HttpResponseInfo* response = trans->GetResponseInfo();
1325 EXPECT_FALSE(response == NULL);
1326
1327 // The password prompt info should have been set in response->auth_challenge.
1328 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1329
1330 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1331 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1332 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1333
1334 TestCompletionCallback callback2;
1335
[email protected]13c8a092010-07-29 06:15:441336 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311337 EXPECT_EQ(ERR_IO_PENDING, rv);
1338
1339 rv = callback2.WaitForResult();
1340 EXPECT_EQ(OK, rv);
1341
1342 response = trans->GetResponseInfo();
1343 ASSERT_FALSE(response == NULL);
1344 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1345 EXPECT_EQ(100, response->headers->GetContentLength());
1346}
1347
[email protected]394816e92010-08-03 07:38:591348// Test the request-challenge-retry sequence for basic auth, over a connection
1349// that requires a restart when setting up an SSL tunnel.
1350TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1351 // Configure against proxy server "myproxy:70".
1352 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1353 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1354 session_deps.net_log = log.bound().net_log();
1355 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1356
1357 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1358
1359 HttpRequestInfo request;
1360 request.method = "GET";
1361 request.url = GURL("https://www.google.com/");
1362 // when the no authentication data flag is set.
1363 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1364
1365 // Since we have proxy, should try to establish tunnel.
1366 MockWrite data_writes1[] = {
1367 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1368 "Host: www.google.com\r\n"
1369 "Proxy-Connection: keep-alive\r\n\r\n"),
1370
1371 // After calling trans->RestartWithAuth(), this is the request we should
1372 // be issuing -- the final header line contains the credentials.
1373 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1374 "Host: www.google.com\r\n"
1375 "Proxy-Connection: keep-alive\r\n"
1376 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1377
1378 MockWrite("GET / HTTP/1.1\r\n"
1379 "Host: www.google.com\r\n"
1380 "Connection: keep-alive\r\n\r\n"),
1381 };
1382
1383 // The proxy responds to the connect with a 407, using a persistent
1384 // connection.
1385 MockRead data_reads1[] = {
1386 // No credentials.
1387 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1388 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1389 MockRead("Proxy-Connection: close\r\n\r\n"),
1390
1391 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1392
1393 MockRead("HTTP/1.1 200 OK\r\n"),
1394 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1395 MockRead("Content-Length: 100\r\n\r\n"),
1396 MockRead(false, OK),
1397 };
1398
1399 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1400 data_writes1, arraysize(data_writes1));
1401 session_deps.socket_factory.AddSocketDataProvider(&data1);
1402 SSLSocketDataProvider ssl(true, OK);
1403 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1404
1405 TestCompletionCallback callback1;
1406
1407 int rv = trans->Start(&request, &callback1, log.bound());
1408 EXPECT_EQ(ERR_IO_PENDING, rv);
1409
1410 rv = callback1.WaitForResult();
1411 EXPECT_EQ(OK, rv);
1412 size_t pos = ExpectLogContainsSomewhere(
1413 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1414 NetLog::PHASE_NONE);
1415 ExpectLogContainsSomewhere(
1416 log.entries(), pos,
1417 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1418 NetLog::PHASE_NONE);
1419
1420 const HttpResponseInfo* response = trans->GetResponseInfo();
1421 ASSERT_FALSE(response == NULL);
1422
1423 EXPECT_EQ(407, response->headers->response_code());
1424 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1425
1426 // The password prompt info should have been set in response->auth_challenge.
1427 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1428
1429 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1430 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1431 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1432
1433 TestCompletionCallback callback2;
1434
1435 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1436 EXPECT_EQ(ERR_IO_PENDING, rv);
1437
1438 rv = callback2.WaitForResult();
1439 EXPECT_EQ(OK, rv);
1440
1441 response = trans->GetResponseInfo();
1442 ASSERT_FALSE(response == NULL);
1443
1444 EXPECT_TRUE(response->headers->IsKeepAlive());
1445 EXPECT_EQ(200, response->headers->response_code());
1446 EXPECT_EQ(100, response->headers->GetContentLength());
1447 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1448
1449 // The password prompt info should not be set.
1450 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1451}
1452
[email protected]11203f012009-11-12 23:02:311453// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321454// proxy connection, when setting up an SSL tunnel.
1455TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1456 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591457 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541458 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1459 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591460 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321461
[email protected]5695b8c2009-09-30 21:36:431462 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321463
[email protected]1c773ea12009-04-28 19:58:421464 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321465 request.method = "GET";
1466 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461467 // Ensure that proxy authentication is attempted even
1468 // when the no authentication data flag is set.
1469 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321470
1471 // Since we have proxy, should try to establish tunnel.
1472 MockWrite data_writes1[] = {
1473 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451474 "Host: www.google.com\r\n"
1475 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321476
1477 // After calling trans->RestartWithAuth(), this is the request we should
1478 // be issuing -- the final header line contains the credentials.
1479 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1480 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451481 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321482 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1483 };
1484
1485 // The proxy responds to the connect with a 407, using a persistent
1486 // connection.
1487 MockRead data_reads1[] = {
1488 // No credentials.
1489 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1490 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1491 MockRead("Content-Length: 10\r\n\r\n"),
1492 MockRead("0123456789"),
1493
1494 // Wrong credentials (wrong password).
1495 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1496 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1497 MockRead("Content-Length: 10\r\n\r\n"),
1498 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421499 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321500 };
1501
[email protected]31a2bfe2010-02-09 08:03:391502 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1503 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591504 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321505
1506 TestCompletionCallback callback1;
1507
[email protected]dbb83db2010-05-11 18:13:391508 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421509 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321510
1511 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421512 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391513 size_t pos = ExpectLogContainsSomewhere(
1514 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1515 NetLog::PHASE_NONE);
1516 ExpectLogContainsSomewhere(
1517 log.entries(), pos,
1518 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1519 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321520
[email protected]1c773ea12009-04-28 19:58:421521 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321522 EXPECT_FALSE(response == NULL);
1523
1524 EXPECT_TRUE(response->headers->IsKeepAlive());
1525 EXPECT_EQ(407, response->headers->response_code());
1526 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421527 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321528
1529 // The password prompt info should have been set in response->auth_challenge.
1530 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1531
[email protected]71e4573a2009-05-21 22:03:001532 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321533 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1534 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1535
1536 TestCompletionCallback callback2;
1537
1538 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441539 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421540 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321541
1542 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421543 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321544
1545 response = trans->GetResponseInfo();
1546 EXPECT_FALSE(response == NULL);
1547
1548 EXPECT_TRUE(response->headers->IsKeepAlive());
1549 EXPECT_EQ(407, response->headers->response_code());
1550 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421551 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321552
1553 // The password prompt info should have been set in response->auth_challenge.
1554 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1555
[email protected]71e4573a2009-05-21 22:03:001556 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321557 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1558 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131559
[email protected]e60e47a2010-07-14 03:37:181560 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1561 // out of scope.
1562 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321563}
1564
[email protected]a8e9b162009-03-12 00:06:441565// Test that we don't read the response body when we fail to establish a tunnel,
1566// even if the user cancels the proxy's auth attempt.
1567TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1568 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591569 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441570
[email protected]e44de5d2009-06-05 20:12:451571 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441572
[email protected]5695b8c2009-09-30 21:36:431573 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441574
[email protected]1c773ea12009-04-28 19:58:421575 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441576 request.method = "GET";
1577 request.url = GURL("https://www.google.com/");
1578 request.load_flags = 0;
1579
1580 // Since we have proxy, should try to establish tunnel.
1581 MockWrite data_writes[] = {
1582 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451583 "Host: www.google.com\r\n"
1584 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441585 };
1586
1587 // The proxy responds to the connect with a 407.
1588 MockRead data_reads[] = {
1589 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1590 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1591 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421592 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441593 };
1594
[email protected]31a2bfe2010-02-09 08:03:391595 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1596 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591597 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441598
1599 TestCompletionCallback callback;
1600
[email protected]5a1d7ca2010-04-28 20:12:271601 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421602 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441603
1604 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421605 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441606
[email protected]1c773ea12009-04-28 19:58:421607 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441608 EXPECT_FALSE(response == NULL);
1609
1610 EXPECT_TRUE(response->headers->IsKeepAlive());
1611 EXPECT_EQ(407, response->headers->response_code());
1612 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421613 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441614
1615 std::string response_data;
1616 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421617 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181618
1619 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1620 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441621}
1622
[email protected]8fdbcd22010-05-05 02:54:521623// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1624// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1625TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1626 // We are using a DIRECT connection (i.e. no proxy) for this session.
1627 SessionDependencies session_deps;
1628 scoped_ptr<HttpTransaction> trans(
1629 new HttpNetworkTransaction(CreateSession(&session_deps)));
1630
1631 HttpRequestInfo request;
1632 request.method = "GET";
1633 request.url = GURL("http://www.google.com/");
1634 request.load_flags = 0;
1635
1636 MockWrite data_writes1[] = {
1637 MockWrite("GET / HTTP/1.1\r\n"
1638 "Host: www.google.com\r\n"
1639 "Connection: keep-alive\r\n\r\n"),
1640 };
1641
1642 MockRead data_reads1[] = {
1643 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1644 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1645 // Large content-length -- won't matter, as connection will be reset.
1646 MockRead("Content-Length: 10000\r\n\r\n"),
1647 MockRead(false, ERR_FAILED),
1648 };
1649
1650 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1651 data_writes1, arraysize(data_writes1));
1652 session_deps.socket_factory.AddSocketDataProvider(&data1);
1653
1654 TestCompletionCallback callback;
1655
1656 int rv = trans->Start(&request, &callback, BoundNetLog());
1657 EXPECT_EQ(ERR_IO_PENDING, rv);
1658
1659 rv = callback.WaitForResult();
1660 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1661}
1662
[email protected]ff007e162009-05-23 09:13:151663void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081664 const MockRead& status, int expected_status) {
1665 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591666 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081667
[email protected]228ff742009-06-05 01:19:591668 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081669
[email protected]5695b8c2009-09-30 21:36:431670 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c744cf22009-02-27 07:28:081671
[email protected]1c773ea12009-04-28 19:58:421672 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081673 request.method = "GET";
1674 request.url = GURL("https://www.google.com/");
1675 request.load_flags = 0;
1676
1677 // Since we have proxy, should try to establish tunnel.
1678 MockWrite data_writes[] = {
1679 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451680 "Host: www.google.com\r\n"
1681 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081682 };
1683
1684 MockRead data_reads[] = {
1685 status,
1686 MockRead("Content-Length: 10\r\n\r\n"),
1687 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421688 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:081689 };
1690
[email protected]31a2bfe2010-02-09 08:03:391691 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1692 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591693 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:081694
1695 TestCompletionCallback callback;
1696
[email protected]5a1d7ca2010-04-28 20:12:271697 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421698 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:081699
1700 rv = callback.WaitForResult();
1701 EXPECT_EQ(expected_status, rv);
1702}
1703
[email protected]ff007e162009-05-23 09:13:151704void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:081705 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:421706 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:081707}
1708
1709TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
1710 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
1711}
1712
1713TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
1714 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
1715}
1716
1717TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
1718 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
1719}
1720
1721TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
1722 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
1723}
1724
1725TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
1726 ConnectStatusHelper(
1727 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
1728}
1729
1730TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
1731 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
1732}
1733
1734TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
1735 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
1736}
1737
1738TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
1739 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
1740}
1741
1742TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
1743 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
1744}
1745
1746TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
1747 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
1748}
1749
1750TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
1751 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
1752}
1753
1754TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
1755 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
1756}
1757
1758TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
1759 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
1760}
1761
1762TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
1763 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
1764}
1765
1766TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
1767 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
1768}
1769
1770TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
1771 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
1772}
1773
1774TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
1775 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
1776}
1777
1778TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
1779 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
1780}
1781
1782TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
1783 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
1784}
1785
1786TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
1787 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
1788}
1789
1790TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
1791 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
1792}
1793
1794TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
1795 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
1796}
1797
1798TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
1799 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
1800}
1801
1802TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
1803 ConnectStatusHelperWithExpectedStatus(
1804 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:541805 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:081806}
1807
1808TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
1809 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
1810}
1811
1812TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
1813 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
1814}
1815
1816TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
1817 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
1818}
1819
1820TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
1821 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
1822}
1823
1824TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
1825 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
1826}
1827
1828TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
1829 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
1830}
1831
1832TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
1833 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
1834}
1835
1836TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
1837 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
1838}
1839
1840TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
1841 ConnectStatusHelper(
1842 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
1843}
1844
1845TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
1846 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
1847}
1848
1849TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
1850 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
1851}
1852
1853TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
1854 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
1855}
1856
1857TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
1858 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
1859}
1860
1861TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
1862 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
1863}
1864
1865TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
1866 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
1867}
1868
1869TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
1870 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
1871}
1872
[email protected]038e9a32008-10-08 22:40:161873// Test the flow when both the proxy server AND origin server require
1874// authentication. Again, this uses basic auth for both since that is
1875// the simplest to mock.
1876TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:591877 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:011878
[email protected]038e9a32008-10-08 22:40:161879 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:421880 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:431881 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161882
[email protected]1c773ea12009-04-28 19:58:421883 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161884 request.method = "GET";
1885 request.url = GURL("http://www.google.com/");
1886 request.load_flags = 0;
1887
[email protected]f9ee6b52008-11-08 06:46:231888 MockWrite data_writes1[] = {
1889 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1890 "Host: www.google.com\r\n"
1891 "Proxy-Connection: keep-alive\r\n\r\n"),
1892 };
1893
[email protected]038e9a32008-10-08 22:40:161894 MockRead data_reads1[] = {
1895 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
1896 // Give a couple authenticate options (only the middle one is actually
1897 // supported).
[email protected]22927ad2009-09-21 19:56:191898 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161899 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1900 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1901 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1902 // Large content-length -- won't matter, as connection will be reset.
1903 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421904 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161905 };
1906
1907 // After calling trans->RestartWithAuth() the first time, this is the
1908 // request we should be issuing -- the final header line contains the
1909 // proxy's credentials.
1910 MockWrite data_writes2[] = {
1911 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1912 "Host: www.google.com\r\n"
1913 "Proxy-Connection: keep-alive\r\n"
1914 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1915 };
1916
1917 // Now the proxy server lets the request pass through to origin server.
1918 // The origin server responds with a 401.
1919 MockRead data_reads2[] = {
1920 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1921 // Note: We are using the same realm-name as the proxy server. This is
1922 // completely valid, as realms are unique across hosts.
1923 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1924 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1925 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421926 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:161927 };
1928
1929 // After calling trans->RestartWithAuth() the second time, we should send
1930 // the credentials for both the proxy and origin server.
1931 MockWrite data_writes3[] = {
1932 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1933 "Host: www.google.com\r\n"
1934 "Proxy-Connection: keep-alive\r\n"
1935 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
1936 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
1937 };
1938
1939 // Lastly we get the desired content.
1940 MockRead data_reads3[] = {
1941 MockRead("HTTP/1.0 200 OK\r\n"),
1942 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1943 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421944 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161945 };
1946
[email protected]31a2bfe2010-02-09 08:03:391947 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1948 data_writes1, arraysize(data_writes1));
1949 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1950 data_writes2, arraysize(data_writes2));
1951 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
1952 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:591953 session_deps.socket_factory.AddSocketDataProvider(&data1);
1954 session_deps.socket_factory.AddSocketDataProvider(&data2);
1955 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:161956
1957 TestCompletionCallback callback1;
1958
[email protected]5a1d7ca2010-04-28 20:12:271959 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421960 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161961
1962 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421963 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161964
[email protected]1c773ea12009-04-28 19:58:421965 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161966 EXPECT_FALSE(response == NULL);
1967
1968 // The password prompt info should have been set in response->auth_challenge.
1969 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1970
[email protected]71e4573a2009-05-21 22:03:001971 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161972 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1973 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1974
1975 TestCompletionCallback callback2;
1976
[email protected]13c8a092010-07-29 06:15:441977 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421978 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161979
1980 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421981 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161982
1983 response = trans->GetResponseInfo();
1984 EXPECT_FALSE(response == NULL);
1985 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1986
[email protected]71e4573a2009-05-21 22:03:001987 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161988 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1989 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1990
1991 TestCompletionCallback callback3;
1992
[email protected]13c8a092010-07-29 06:15:441993 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:421994 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161995
1996 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421997 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161998
1999 response = trans->GetResponseInfo();
2000 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2001 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162002}
[email protected]4ddaf2502008-10-23 18:26:192003
[email protected]ea9dc9a2009-09-05 00:43:322004// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2005// can't hook into its internals to cause it to generate predictable NTLM
2006// authorization headers.
2007#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292008// The NTLM authentication unit tests were generated by capturing the HTTP
2009// requests and responses using Fiddler 2 and inspecting the generated random
2010// bytes in the debugger.
2011
2012// Enter the correct password and authenticate successfully.
2013TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422014 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112015 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592016 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402017 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432018 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3f918782009-02-28 01:29:242019
[email protected]1c773ea12009-04-28 19:58:422020 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242021 request.method = "GET";
2022 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2023 request.load_flags = 0;
2024
2025 MockWrite data_writes1[] = {
2026 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2027 "Host: 172.22.68.17\r\n"
2028 "Connection: keep-alive\r\n\r\n"),
2029 };
2030
2031 MockRead data_reads1[] = {
2032 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042033 // Negotiate and NTLM are often requested together. However, we only want
2034 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2035 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242036 MockRead("WWW-Authenticate: NTLM\r\n"),
2037 MockRead("Connection: close\r\n"),
2038 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362039 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242040 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422041 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242042 };
2043
2044 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222045 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242046 // request we should be issuing -- the final header line contains a Type
2047 // 1 message.
2048 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2049 "Host: 172.22.68.17\r\n"
2050 "Connection: keep-alive\r\n"
2051 "Authorization: NTLM "
2052 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2053
2054 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2055 // (the credentials for the origin server). The second request continues
2056 // on the same connection.
2057 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2058 "Host: 172.22.68.17\r\n"
2059 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292060 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2061 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2062 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2063 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2064 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242065 };
2066
2067 MockRead data_reads2[] = {
2068 // The origin server responds with a Type 2 message.
2069 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2070 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292071 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242072 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2073 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2074 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2075 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2076 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2077 "BtAAAAAAA=\r\n"),
2078 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362079 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242080 MockRead("You are not authorized to view this page\r\n"),
2081
2082 // Lastly we get the desired content.
2083 MockRead("HTTP/1.1 200 OK\r\n"),
2084 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2085 MockRead("Content-Length: 13\r\n\r\n"),
2086 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422087 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242088 };
2089
[email protected]31a2bfe2010-02-09 08:03:392090 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2091 data_writes1, arraysize(data_writes1));
2092 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2093 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592094 session_deps.socket_factory.AddSocketDataProvider(&data1);
2095 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242096
2097 TestCompletionCallback callback1;
2098
[email protected]5a1d7ca2010-04-28 20:12:272099 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422100 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242101
2102 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422103 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242104
[email protected]0757e7702009-03-27 04:00:222105 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2106 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442107 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222109 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422110 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222111 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2112
[email protected]1c773ea12009-04-28 19:58:422113 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042114 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242115
[email protected]aef04272010-06-28 18:03:042116 // The password prompt info should have been set in
2117 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242118 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2119
[email protected]71e4573a2009-05-21 22:03:002120 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242121 EXPECT_EQ(L"", response->auth_challenge->realm);
2122 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2123
[email protected]0757e7702009-03-27 04:00:222124 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242125
[email protected]13c8a092010-07-29 06:15:442126 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422127 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242128
[email protected]0757e7702009-03-27 04:00:222129 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422130 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242131
2132 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042133 ASSERT_FALSE(response == NULL);
2134
[email protected]3f918782009-02-28 01:29:242135 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2136 EXPECT_EQ(13, response->headers->GetContentLength());
2137}
2138
[email protected]385a4672009-03-11 22:21:292139// Enter a wrong password, and then the correct one.
2140TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422141 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112142 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592143 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402144 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432145 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]385a4672009-03-11 22:21:292146
[email protected]1c773ea12009-04-28 19:58:422147 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292148 request.method = "GET";
2149 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2150 request.load_flags = 0;
2151
2152 MockWrite data_writes1[] = {
2153 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2154 "Host: 172.22.68.17\r\n"
2155 "Connection: keep-alive\r\n\r\n"),
2156 };
2157
2158 MockRead data_reads1[] = {
2159 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042160 // Negotiate and NTLM are often requested together. However, we only want
2161 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2162 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292163 MockRead("WWW-Authenticate: NTLM\r\n"),
2164 MockRead("Connection: close\r\n"),
2165 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362166 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292167 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422168 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292169 };
2170
2171 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222172 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292173 // request we should be issuing -- the final header line contains a Type
2174 // 1 message.
2175 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2176 "Host: 172.22.68.17\r\n"
2177 "Connection: keep-alive\r\n"
2178 "Authorization: NTLM "
2179 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2180
2181 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2182 // (the credentials for the origin server). The second request continues
2183 // on the same connection.
2184 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2185 "Host: 172.22.68.17\r\n"
2186 "Connection: keep-alive\r\n"
2187 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2188 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2189 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2190 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2191 "4Ww7b7E=\r\n\r\n"),
2192 };
2193
2194 MockRead data_reads2[] = {
2195 // The origin server responds with a Type 2 message.
2196 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2197 MockRead("WWW-Authenticate: NTLM "
2198 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2199 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2200 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2201 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2202 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2203 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2204 "BtAAAAAAA=\r\n"),
2205 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362206 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292207 MockRead("You are not authorized to view this page\r\n"),
2208
2209 // Wrong password.
2210 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292211 MockRead("WWW-Authenticate: NTLM\r\n"),
2212 MockRead("Connection: close\r\n"),
2213 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362214 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292215 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422216 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292217 };
2218
2219 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222220 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292221 // request we should be issuing -- the final header line contains a Type
2222 // 1 message.
2223 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2224 "Host: 172.22.68.17\r\n"
2225 "Connection: keep-alive\r\n"
2226 "Authorization: NTLM "
2227 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2228
2229 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2230 // (the credentials for the origin server). The second request continues
2231 // on the same connection.
2232 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2233 "Host: 172.22.68.17\r\n"
2234 "Connection: keep-alive\r\n"
2235 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2236 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2237 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2238 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2239 "+4MUm7c=\r\n\r\n"),
2240 };
2241
2242 MockRead data_reads3[] = {
2243 // The origin server responds with a Type 2 message.
2244 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2245 MockRead("WWW-Authenticate: NTLM "
2246 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2247 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2248 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2249 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2250 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2251 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2252 "BtAAAAAAA=\r\n"),
2253 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362254 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292255 MockRead("You are not authorized to view this page\r\n"),
2256
2257 // Lastly we get the desired content.
2258 MockRead("HTTP/1.1 200 OK\r\n"),
2259 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2260 MockRead("Content-Length: 13\r\n\r\n"),
2261 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422262 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292263 };
2264
[email protected]31a2bfe2010-02-09 08:03:392265 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2266 data_writes1, arraysize(data_writes1));
2267 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2268 data_writes2, arraysize(data_writes2));
2269 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2270 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592271 session_deps.socket_factory.AddSocketDataProvider(&data1);
2272 session_deps.socket_factory.AddSocketDataProvider(&data2);
2273 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292274
2275 TestCompletionCallback callback1;
2276
[email protected]5a1d7ca2010-04-28 20:12:272277 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422278 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292279
2280 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422281 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292282
[email protected]0757e7702009-03-27 04:00:222283 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292284 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442285 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422286 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292287 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422288 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222289 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292290
[email protected]1c773ea12009-04-28 19:58:422291 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292292 EXPECT_FALSE(response == NULL);
2293
2294 // The password prompt info should have been set in response->auth_challenge.
2295 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2296
[email protected]71e4573a2009-05-21 22:03:002297 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292298 EXPECT_EQ(L"", response->auth_challenge->realm);
2299 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2300
2301 TestCompletionCallback callback3;
2302
[email protected]0757e7702009-03-27 04:00:222303 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442304 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422305 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292306
2307 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422308 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292309
[email protected]0757e7702009-03-27 04:00:222310 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2311 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442312 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422313 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222314 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422315 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222316 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2317
2318 response = trans->GetResponseInfo();
2319 EXPECT_FALSE(response == NULL);
2320
2321 // The password prompt info should have been set in response->auth_challenge.
2322 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2323
[email protected]71e4573a2009-05-21 22:03:002324 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222325 EXPECT_EQ(L"", response->auth_challenge->realm);
2326 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2327
2328 TestCompletionCallback callback5;
2329
2330 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442331 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422332 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222333
2334 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422335 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222336
[email protected]385a4672009-03-11 22:21:292337 response = trans->GetResponseInfo();
2338 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2339 EXPECT_EQ(13, response->headers->GetContentLength());
2340}
[email protected]ea9dc9a2009-09-05 00:43:322341#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292342
[email protected]4ddaf2502008-10-23 18:26:192343// Test reading a server response which has only headers, and no body.
2344// After some maximum number of bytes is consumed, the transaction should
2345// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2346TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592347 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402348 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432349 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192350
[email protected]1c773ea12009-04-28 19:58:422351 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192352 request.method = "GET";
2353 request.url = GURL("http://www.google.com/");
2354 request.load_flags = 0;
2355
[email protected]b75b7b2f2009-10-06 00:54:532356 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432357 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532358 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192359
2360 MockRead data_reads[] = {
2361 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432362 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192363 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422364 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192365 };
[email protected]31a2bfe2010-02-09 08:03:392366 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592367 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192368
2369 TestCompletionCallback callback;
2370
[email protected]5a1d7ca2010-04-28 20:12:272371 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422372 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192373
2374 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422375 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192376
[email protected]1c773ea12009-04-28 19:58:422377 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192378 EXPECT_TRUE(response == NULL);
2379}
[email protected]f4e426b2008-11-05 00:24:492380
2381// Make sure that we don't try to reuse a TCPClientSocket when failing to
2382// establish tunnel.
2383// http://code.google.com/p/chromium/issues/detail?id=3772
2384TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2385 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592386 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012387
[email protected]228ff742009-06-05 01:19:592388 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492389
[email protected]5695b8c2009-09-30 21:36:432390 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492391
[email protected]1c773ea12009-04-28 19:58:422392 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492393 request.method = "GET";
2394 request.url = GURL("https://www.google.com/");
2395 request.load_flags = 0;
2396
2397 // Since we have proxy, should try to establish tunnel.
2398 MockWrite data_writes1[] = {
2399 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452400 "Host: www.google.com\r\n"
2401 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492402 };
2403
[email protected]77848d12008-11-14 00:00:222404 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492405 // connection. Usually a proxy would return 501 (not implemented),
2406 // or 200 (tunnel established).
2407 MockRead data_reads1[] = {
2408 MockRead("HTTP/1.1 404 Not Found\r\n"),
2409 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422410 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492411 };
2412
[email protected]31a2bfe2010-02-09 08:03:392413 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2414 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592415 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492416
2417 TestCompletionCallback callback1;
2418
[email protected]5a1d7ca2010-04-28 20:12:272419 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422420 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492421
2422 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422423 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492424
[email protected]1c773ea12009-04-28 19:58:422425 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082426 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492427
[email protected]b4404c02009-04-10 16:38:522428 // Empty the current queue. This is necessary because idle sockets are
2429 // added to the connection pool asynchronously with a PostTask.
2430 MessageLoop::current()->RunAllPending();
2431
[email protected]f4e426b2008-11-05 00:24:492432 // We now check to make sure the TCPClientSocket was not added back to
2433 // the pool.
[email protected]a937a06d2009-08-19 21:19:242434 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492435 trans.reset();
[email protected]b4404c02009-04-10 16:38:522436 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492437 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242438 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492439}
[email protected]372d34a2008-11-05 21:30:512440
[email protected]1b157c02009-04-21 01:55:402441// Make sure that we recycle a socket after reading all of the response body.
2442TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592443 SessionDependencies session_deps;
2444 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402445
[email protected]5695b8c2009-09-30 21:36:432446 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402447
[email protected]1c773ea12009-04-28 19:58:422448 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402449 request.method = "GET";
2450 request.url = GURL("http://www.google.com/");
2451 request.load_flags = 0;
2452
2453 MockRead data_reads[] = {
2454 // A part of the response body is received with the response headers.
2455 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2456 // The rest of the response body is received in two parts.
2457 MockRead("lo"),
2458 MockRead(" world"),
2459 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422460 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402461 };
2462
[email protected]31a2bfe2010-02-09 08:03:392463 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592464 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402465
2466 TestCompletionCallback callback;
2467
[email protected]5a1d7ca2010-04-28 20:12:272468 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422469 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402470
2471 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422472 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402473
[email protected]1c773ea12009-04-28 19:58:422474 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402475 EXPECT_TRUE(response != NULL);
2476
2477 EXPECT_TRUE(response->headers != NULL);
2478 std::string status_line = response->headers->GetStatusLine();
2479 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2480
[email protected]a937a06d2009-08-19 21:19:242481 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402482
2483 std::string response_data;
2484 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422485 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402486 EXPECT_EQ("hello world", response_data);
2487
2488 // Empty the current queue. This is necessary because idle sockets are
2489 // added to the connection pool asynchronously with a PostTask.
2490 MessageLoop::current()->RunAllPending();
2491
2492 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242493 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402494}
2495
[email protected]b4404c02009-04-10 16:38:522496// Make sure that we recycle a socket after a zero-length response.
2497// http://crbug.com/9880
2498TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592499 SessionDependencies session_deps;
2500 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522501
[email protected]5695b8c2009-09-30 21:36:432502 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522503
[email protected]1c773ea12009-04-28 19:58:422504 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522505 request.method = "GET";
2506 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2507 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2508 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2509 "rt=prt.2642,ol.2649,xjs.2951");
2510 request.load_flags = 0;
2511
2512 MockRead data_reads[] = {
2513 MockRead("HTTP/1.1 204 No Content\r\n"
2514 "Content-Length: 0\r\n"
2515 "Content-Type: text/html\r\n\r\n"),
2516 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422517 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522518 };
2519
[email protected]31a2bfe2010-02-09 08:03:392520 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592521 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522522
2523 TestCompletionCallback callback;
2524
[email protected]5a1d7ca2010-04-28 20:12:272525 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422526 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:522527
2528 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422529 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522530
[email protected]1c773ea12009-04-28 19:58:422531 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:522532 EXPECT_TRUE(response != NULL);
2533
2534 EXPECT_TRUE(response->headers != NULL);
2535 std::string status_line = response->headers->GetStatusLine();
2536 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
2537
[email protected]a937a06d2009-08-19 21:19:242538 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522539
2540 std::string response_data;
2541 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422542 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:522543 EXPECT_EQ("", response_data);
2544
2545 // Empty the current queue. This is necessary because idle sockets are
2546 // added to the connection pool asynchronously with a PostTask.
2547 MessageLoop::current()->RunAllPending();
2548
2549 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242550 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:522551}
2552
[email protected]372d34a2008-11-05 21:30:512553TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:422554 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:512555 // Transaction 1: a GET request that succeeds. The socket is recycled
2556 // after use.
2557 request[0].method = "GET";
2558 request[0].url = GURL("http://www.google.com/");
2559 request[0].load_flags = 0;
2560 // Transaction 2: a POST request. Reuses the socket kept alive from
2561 // transaction 1. The first attempts fails when writing the POST data.
2562 // This causes the transaction to retry with a new socket. The second
2563 // attempt succeeds.
2564 request[1].method = "POST";
2565 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:422566 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:512567 request[1].upload_data->AppendBytes("foo", 3);
2568 request[1].load_flags = 0;
2569
[email protected]228ff742009-06-05 01:19:592570 SessionDependencies session_deps;
2571 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:512572
2573 // The first socket is used for transaction 1 and the first attempt of
2574 // transaction 2.
2575
2576 // The response of transaction 1.
2577 MockRead data_reads1[] = {
2578 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
2579 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:422580 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512581 };
2582 // The mock write results of transaction 1 and the first attempt of
2583 // transaction 2.
2584 MockWrite data_writes1[] = {
2585 MockWrite(false, 64), // GET
2586 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:422587 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:512588 };
[email protected]31a2bfe2010-02-09 08:03:392589 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2590 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:512591
2592 // The second socket is used for the second attempt of transaction 2.
2593
2594 // The response of transaction 2.
2595 MockRead data_reads2[] = {
2596 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
2597 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:422598 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:512599 };
2600 // The mock write results of the second attempt of transaction 2.
2601 MockWrite data_writes2[] = {
2602 MockWrite(false, 93), // POST
2603 MockWrite(false, 3), // POST data
2604 };
[email protected]31a2bfe2010-02-09 08:03:392605 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2606 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:512607
[email protected]5ecc992a42009-11-11 01:41:592608 session_deps.socket_factory.AddSocketDataProvider(&data1);
2609 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:512610
2611 const char* kExpectedResponseData[] = {
2612 "hello world", "welcome"
2613 };
2614
2615 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:422616 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432617 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:512618
2619 TestCompletionCallback callback;
2620
[email protected]5a1d7ca2010-04-28 20:12:272621 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422622 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:512623
2624 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422625 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512626
[email protected]1c773ea12009-04-28 19:58:422627 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:512628 EXPECT_TRUE(response != NULL);
2629
2630 EXPECT_TRUE(response->headers != NULL);
2631 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2632
2633 std::string response_data;
2634 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422635 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:512636 EXPECT_EQ(kExpectedResponseData[i], response_data);
2637 }
2638}
[email protected]f9ee6b52008-11-08 06:46:232639
2640// Test the request-challenge-retry sequence for basic auth when there is
2641// an identity in the URL. The request should be sent as normal, but when
2642// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:322643TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:592644 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402645 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432646 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:232647
[email protected]1c773ea12009-04-28 19:58:422648 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232649 request.method = "GET";
2650 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:292651 request.url = GURL("http://foo:b@[email protected]/");
2652
2653 // The password contains an escaped character -- for this test to pass it
2654 // will need to be unescaped by HttpNetworkTransaction.
2655 EXPECT_EQ("b%40r", request.url.password());
2656
[email protected]ea9dc9a2009-09-05 00:43:322657 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:232658
2659 MockWrite data_writes1[] = {
2660 MockWrite("GET / HTTP/1.1\r\n"
2661 "Host: www.google.com\r\n"
2662 "Connection: keep-alive\r\n\r\n"),
2663 };
2664
2665 MockRead data_reads1[] = {
2666 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2667 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2668 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422669 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232670 };
2671
2672 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:322673 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:232674 MockWrite data_writes2[] = {
2675 MockWrite("GET / HTTP/1.1\r\n"
2676 "Host: www.google.com\r\n"
2677 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:292678 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:232679 };
2680
2681 MockRead data_reads2[] = {
2682 MockRead("HTTP/1.0 200 OK\r\n"),
2683 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422684 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232685 };
2686
[email protected]31a2bfe2010-02-09 08:03:392687 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2688 data_writes1, arraysize(data_writes1));
2689 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2690 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592691 session_deps.socket_factory.AddSocketDataProvider(&data1);
2692 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232693
2694 TestCompletionCallback callback1;
2695
[email protected]5a1d7ca2010-04-28 20:12:272696 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232698
2699 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422700 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232701
[email protected]0757e7702009-03-27 04:00:222702 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2703 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442704 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422705 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222706 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422707 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222708 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2709
[email protected]1c773ea12009-04-28 19:58:422710 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232711 EXPECT_FALSE(response == NULL);
2712
2713 // There is no challenge info, since the identity in URL worked.
2714 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2715
2716 EXPECT_EQ(100, response->headers->GetContentLength());
2717
2718 // Empty the current queue.
2719 MessageLoop::current()->RunAllPending();
2720}
2721
[email protected]ea9dc9a2009-09-05 00:43:322722// Test the request-challenge-retry sequence for basic auth when there is
2723// an incorrect identity in the URL. The identity from the URL should be used
2724// only once.
2725TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
2726 SessionDependencies session_deps;
2727 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432728 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:322729
2730 HttpRequestInfo request;
2731 request.method = "GET";
2732 // Note: the URL has a username:password in it. The password "baz" is
2733 // wrong (should be "bar").
2734 request.url = GURL("http://foo:[email protected]/");
2735
2736 request.load_flags = LOAD_NORMAL;
2737
2738 MockWrite data_writes1[] = {
2739 MockWrite("GET / HTTP/1.1\r\n"
2740 "Host: www.google.com\r\n"
2741 "Connection: keep-alive\r\n\r\n"),
2742 };
2743
2744 MockRead data_reads1[] = {
2745 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2746 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2747 MockRead("Content-Length: 10\r\n\r\n"),
2748 MockRead(false, ERR_FAILED),
2749 };
2750
2751 // After the challenge above, the transaction will be restarted using the
2752 // identity from the url (foo, baz) to answer the challenge.
2753 MockWrite data_writes2[] = {
2754 MockWrite("GET / HTTP/1.1\r\n"
2755 "Host: www.google.com\r\n"
2756 "Connection: keep-alive\r\n"
2757 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
2758 };
2759
2760 MockRead data_reads2[] = {
2761 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2762 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2763 MockRead("Content-Length: 10\r\n\r\n"),
2764 MockRead(false, ERR_FAILED),
2765 };
2766
2767 // After the challenge above, the transaction will be restarted using the
2768 // identity supplied by the user (foo, bar) to answer the challenge.
2769 MockWrite data_writes3[] = {
2770 MockWrite("GET / HTTP/1.1\r\n"
2771 "Host: www.google.com\r\n"
2772 "Connection: keep-alive\r\n"
2773 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2774 };
2775
2776 MockRead data_reads3[] = {
2777 MockRead("HTTP/1.0 200 OK\r\n"),
2778 MockRead("Content-Length: 100\r\n\r\n"),
2779 MockRead(false, OK),
2780 };
2781
[email protected]31a2bfe2010-02-09 08:03:392782 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2783 data_writes1, arraysize(data_writes1));
2784 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2785 data_writes2, arraysize(data_writes2));
2786 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2787 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592788 session_deps.socket_factory.AddSocketDataProvider(&data1);
2789 session_deps.socket_factory.AddSocketDataProvider(&data2);
2790 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:322791
2792 TestCompletionCallback callback1;
2793
[email protected]5a1d7ca2010-04-28 20:12:272794 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:322795 EXPECT_EQ(ERR_IO_PENDING, rv);
2796
2797 rv = callback1.WaitForResult();
2798 EXPECT_EQ(OK, rv);
2799
2800 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2801 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442802 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:322803 EXPECT_EQ(ERR_IO_PENDING, rv);
2804 rv = callback2.WaitForResult();
2805 EXPECT_EQ(OK, rv);
2806 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2807
2808 const HttpResponseInfo* response = trans->GetResponseInfo();
2809 EXPECT_FALSE(response == NULL);
2810 // The password prompt info should have been set in response->auth_challenge.
2811 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2812
2813 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
2814 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2815 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2816
2817 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:442818 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:322819 EXPECT_EQ(ERR_IO_PENDING, rv);
2820 rv = callback3.WaitForResult();
2821 EXPECT_EQ(OK, rv);
2822 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2823
2824 response = trans->GetResponseInfo();
2825 EXPECT_FALSE(response == NULL);
2826
2827 // There is no challenge info, since the identity worked.
2828 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2829
2830 EXPECT_EQ(100, response->headers->GetContentLength());
2831
2832 // Empty the current queue.
2833 MessageLoop::current()->RunAllPending();
2834}
2835
[email protected]f9ee6b52008-11-08 06:46:232836// Test that previously tried username/passwords for a realm get re-used.
2837TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:592838 SessionDependencies session_deps;
2839 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:232840
2841 // Transaction 1: authenticate (foo, bar) on MyRealm1
2842 {
[email protected]5695b8c2009-09-30 21:36:432843 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232844
[email protected]1c773ea12009-04-28 19:58:422845 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232846 request.method = "GET";
2847 request.url = GURL("http://www.google.com/x/y/z");
2848 request.load_flags = 0;
2849
2850 MockWrite data_writes1[] = {
2851 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2852 "Host: www.google.com\r\n"
2853 "Connection: keep-alive\r\n\r\n"),
2854 };
2855
2856 MockRead data_reads1[] = {
2857 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2858 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2859 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422860 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232861 };
2862
2863 // Resend with authorization (username=foo, password=bar)
2864 MockWrite data_writes2[] = {
2865 MockWrite("GET /x/y/z HTTP/1.1\r\n"
2866 "Host: www.google.com\r\n"
2867 "Connection: keep-alive\r\n"
2868 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2869 };
2870
2871 // Sever accepts the authorization.
2872 MockRead data_reads2[] = {
2873 MockRead("HTTP/1.0 200 OK\r\n"),
2874 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422875 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232876 };
2877
[email protected]31a2bfe2010-02-09 08:03:392878 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2879 data_writes1, arraysize(data_writes1));
2880 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2881 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592882 session_deps.socket_factory.AddSocketDataProvider(&data1);
2883 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232884
2885 TestCompletionCallback callback1;
2886
[email protected]5a1d7ca2010-04-28 20:12:272887 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422888 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232889
2890 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422891 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232892
[email protected]1c773ea12009-04-28 19:58:422893 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232894 EXPECT_FALSE(response == NULL);
2895
2896 // The password prompt info should have been set in
2897 // response->auth_challenge.
2898 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2899
[email protected]71e4573a2009-05-21 22:03:002900 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232901 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2902 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2903
2904 TestCompletionCallback callback2;
2905
[email protected]13c8a092010-07-29 06:15:442906 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422907 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232908
2909 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422910 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232911
2912 response = trans->GetResponseInfo();
2913 EXPECT_FALSE(response == NULL);
2914 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2915 EXPECT_EQ(100, response->headers->GetContentLength());
2916 }
2917
2918 // ------------------------------------------------------------------------
2919
2920 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
2921 {
[email protected]5695b8c2009-09-30 21:36:432922 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:232923
[email protected]1c773ea12009-04-28 19:58:422924 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:232925 request.method = "GET";
2926 // Note that Transaction 1 was at /x/y/z, so this is in the same
2927 // protection space as MyRealm1.
2928 request.url = GURL("http://www.google.com/x/y/a/b");
2929 request.load_flags = 0;
2930
2931 MockWrite data_writes1[] = {
2932 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2933 "Host: www.google.com\r\n"
2934 "Connection: keep-alive\r\n"
2935 // Send preemptive authorization for MyRealm1
2936 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2937 };
2938
2939 // The server didn't like the preemptive authorization, and
2940 // challenges us for a different realm (MyRealm2).
2941 MockRead data_reads1[] = {
2942 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2943 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
2944 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422945 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:232946 };
2947
2948 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
2949 MockWrite data_writes2[] = {
2950 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
2951 "Host: www.google.com\r\n"
2952 "Connection: keep-alive\r\n"
2953 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2954 };
2955
2956 // Sever accepts the authorization.
2957 MockRead data_reads2[] = {
2958 MockRead("HTTP/1.0 200 OK\r\n"),
2959 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422960 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:232961 };
2962
[email protected]31a2bfe2010-02-09 08:03:392963 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2964 data_writes1, arraysize(data_writes1));
2965 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2966 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592967 session_deps.socket_factory.AddSocketDataProvider(&data1);
2968 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:232969
2970 TestCompletionCallback callback1;
2971
[email protected]5a1d7ca2010-04-28 20:12:272972 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422973 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232974
2975 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422976 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232977
[email protected]1c773ea12009-04-28 19:58:422978 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:232979 EXPECT_FALSE(response == NULL);
2980
2981 // The password prompt info should have been set in
2982 // response->auth_challenge.
2983 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2984
[email protected]71e4573a2009-05-21 22:03:002985 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:232986 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
2987 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2988
2989 TestCompletionCallback callback2;
2990
[email protected]13c8a092010-07-29 06:15:442991 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:422992 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:232993
2994 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422995 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:232996
2997 response = trans->GetResponseInfo();
2998 EXPECT_FALSE(response == NULL);
2999 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3000 EXPECT_EQ(100, response->headers->GetContentLength());
3001 }
3002
3003 // ------------------------------------------------------------------------
3004
3005 // Transaction 3: Resend a request in MyRealm's protection space --
3006 // succeed with preemptive authorization.
3007 {
[email protected]5695b8c2009-09-30 21:36:433008 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233009
[email protected]1c773ea12009-04-28 19:58:423010 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233011 request.method = "GET";
3012 request.url = GURL("http://www.google.com/x/y/z2");
3013 request.load_flags = 0;
3014
3015 MockWrite data_writes1[] = {
3016 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3017 "Host: www.google.com\r\n"
3018 "Connection: keep-alive\r\n"
3019 // The authorization for MyRealm1 gets sent preemptively
3020 // (since the url is in the same protection space)
3021 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3022 };
3023
3024 // Sever accepts the preemptive authorization
3025 MockRead data_reads1[] = {
3026 MockRead("HTTP/1.0 200 OK\r\n"),
3027 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423028 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233029 };
3030
[email protected]31a2bfe2010-02-09 08:03:393031 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3032 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593033 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233034
3035 TestCompletionCallback callback1;
3036
[email protected]5a1d7ca2010-04-28 20:12:273037 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423038 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233039
3040 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423041 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233042
[email protected]1c773ea12009-04-28 19:58:423043 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233044 EXPECT_FALSE(response == NULL);
3045
3046 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3047 EXPECT_EQ(100, response->headers->GetContentLength());
3048 }
3049
3050 // ------------------------------------------------------------------------
3051
3052 // Transaction 4: request another URL in MyRealm (however the
3053 // url is not known to belong to the protection space, so no pre-auth).
3054 {
[email protected]5695b8c2009-09-30 21:36:433055 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233056
[email protected]1c773ea12009-04-28 19:58:423057 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233058 request.method = "GET";
3059 request.url = GURL("http://www.google.com/x/1");
3060 request.load_flags = 0;
3061
3062 MockWrite data_writes1[] = {
3063 MockWrite("GET /x/1 HTTP/1.1\r\n"
3064 "Host: www.google.com\r\n"
3065 "Connection: keep-alive\r\n\r\n"),
3066 };
3067
3068 MockRead data_reads1[] = {
3069 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3070 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3071 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423072 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233073 };
3074
3075 // Resend with authorization from MyRealm's cache.
3076 MockWrite data_writes2[] = {
3077 MockWrite("GET /x/1 HTTP/1.1\r\n"
3078 "Host: www.google.com\r\n"
3079 "Connection: keep-alive\r\n"
3080 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3081 };
3082
3083 // Sever accepts the authorization.
3084 MockRead data_reads2[] = {
3085 MockRead("HTTP/1.0 200 OK\r\n"),
3086 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423087 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233088 };
3089
[email protected]31a2bfe2010-02-09 08:03:393090 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3091 data_writes1, arraysize(data_writes1));
3092 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3093 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593094 session_deps.socket_factory.AddSocketDataProvider(&data1);
3095 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233096
3097 TestCompletionCallback callback1;
3098
[email protected]5a1d7ca2010-04-28 20:12:273099 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423100 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233101
3102 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423103 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233104
[email protected]0757e7702009-03-27 04:00:223105 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3106 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443107 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223109 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423110 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223111 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3112
[email protected]1c773ea12009-04-28 19:58:423113 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233114 EXPECT_FALSE(response == NULL);
3115 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3116 EXPECT_EQ(100, response->headers->GetContentLength());
3117 }
3118
3119 // ------------------------------------------------------------------------
3120
3121 // Transaction 5: request a URL in MyRealm, but the server rejects the
3122 // cached identity. Should invalidate and re-prompt.
3123 {
[email protected]5695b8c2009-09-30 21:36:433124 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233125
[email protected]1c773ea12009-04-28 19:58:423126 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233127 request.method = "GET";
3128 request.url = GURL("http://www.google.com/p/q/t");
3129 request.load_flags = 0;
3130
3131 MockWrite data_writes1[] = {
3132 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3133 "Host: www.google.com\r\n"
3134 "Connection: keep-alive\r\n\r\n"),
3135 };
3136
3137 MockRead data_reads1[] = {
3138 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3139 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3140 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423141 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233142 };
3143
3144 // Resend with authorization from cache for MyRealm.
3145 MockWrite data_writes2[] = {
3146 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3147 "Host: www.google.com\r\n"
3148 "Connection: keep-alive\r\n"
3149 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3150 };
3151
3152 // Sever rejects the authorization.
3153 MockRead data_reads2[] = {
3154 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3155 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3156 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423157 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233158 };
3159
3160 // At this point we should prompt for new credentials for MyRealm.
3161 // Restart with username=foo3, password=foo4.
3162 MockWrite data_writes3[] = {
3163 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3164 "Host: www.google.com\r\n"
3165 "Connection: keep-alive\r\n"
3166 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3167 };
3168
3169 // Sever accepts the authorization.
3170 MockRead data_reads3[] = {
3171 MockRead("HTTP/1.0 200 OK\r\n"),
3172 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423173 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233174 };
3175
[email protected]31a2bfe2010-02-09 08:03:393176 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3177 data_writes1, arraysize(data_writes1));
3178 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3179 data_writes2, arraysize(data_writes2));
3180 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3181 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593182 session_deps.socket_factory.AddSocketDataProvider(&data1);
3183 session_deps.socket_factory.AddSocketDataProvider(&data2);
3184 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233185
3186 TestCompletionCallback callback1;
3187
[email protected]5a1d7ca2010-04-28 20:12:273188 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423189 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233190
3191 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423192 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233193
[email protected]0757e7702009-03-27 04:00:223194 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3195 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443196 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423197 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223198 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423199 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223200 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3201
[email protected]1c773ea12009-04-28 19:58:423202 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233203 EXPECT_FALSE(response == NULL);
3204
3205 // The password prompt info should have been set in
3206 // response->auth_challenge.
3207 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3208
[email protected]71e4573a2009-05-21 22:03:003209 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233210 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3211 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3212
[email protected]0757e7702009-03-27 04:00:223213 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233214
[email protected]13c8a092010-07-29 06:15:443215 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423216 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233217
[email protected]0757e7702009-03-27 04:00:223218 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423219 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233220
3221 response = trans->GetResponseInfo();
3222 EXPECT_FALSE(response == NULL);
3223 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3224 EXPECT_EQ(100, response->headers->GetContentLength());
3225 }
3226}
[email protected]89ceba9a2009-03-21 03:46:063227
[email protected]3c32c5f2010-05-18 15:18:123228// Tests that nonce count increments when multiple auth attempts
3229// are started with the same nonce.
3230TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3231 SessionDependencies session_deps;
3232 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3233 HttpAuthHandlerDigest::SetFixedCnonce(true);
3234
3235 // Transaction 1: authenticate (foo, bar) on MyRealm1
3236 {
3237 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3238
3239 HttpRequestInfo request;
3240 request.method = "GET";
3241 request.url = GURL("http://www.google.com/x/y/z");
3242 request.load_flags = 0;
3243
3244 MockWrite data_writes1[] = {
3245 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3246 "Host: www.google.com\r\n"
3247 "Connection: keep-alive\r\n\r\n"),
3248 };
3249
3250 MockRead data_reads1[] = {
3251 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3252 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3253 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3254 MockRead(false, OK),
3255 };
3256
3257 // Resend with authorization (username=foo, password=bar)
3258 MockWrite data_writes2[] = {
3259 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3260 "Host: www.google.com\r\n"
3261 "Connection: keep-alive\r\n"
3262 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3263 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3264 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3265 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3266 };
3267
3268 // Sever accepts the authorization.
3269 MockRead data_reads2[] = {
3270 MockRead("HTTP/1.0 200 OK\r\n"),
3271 MockRead(false, OK),
3272 };
3273
3274 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3275 data_writes1, arraysize(data_writes1));
3276 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3277 data_writes2, arraysize(data_writes2));
3278 session_deps.socket_factory.AddSocketDataProvider(&data1);
3279 session_deps.socket_factory.AddSocketDataProvider(&data2);
3280
3281 TestCompletionCallback callback1;
3282
3283 int rv = trans->Start(&request, &callback1, BoundNetLog());
3284 EXPECT_EQ(ERR_IO_PENDING, rv);
3285
3286 rv = callback1.WaitForResult();
3287 EXPECT_EQ(OK, rv);
3288
3289 const HttpResponseInfo* response = trans->GetResponseInfo();
3290 ASSERT_FALSE(response == NULL);
3291
3292 // The password prompt info should have been set in
3293 // response->auth_challenge.
3294 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3295
3296 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3297 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3298 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3299
3300 TestCompletionCallback callback2;
3301
[email protected]13c8a092010-07-29 06:15:443302 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123303 EXPECT_EQ(ERR_IO_PENDING, rv);
3304
3305 rv = callback2.WaitForResult();
3306 EXPECT_EQ(OK, rv);
3307
3308 response = trans->GetResponseInfo();
3309 ASSERT_FALSE(response == NULL);
3310 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3311 }
3312
3313 // ------------------------------------------------------------------------
3314
3315 // Transaction 2: Request another resource in digestive's protection space.
3316 // This will preemptively add an Authorization header which should have an
3317 // "nc" value of 2 (as compared to 1 in the first use.
3318 {
3319 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3320
3321 HttpRequestInfo request;
3322 request.method = "GET";
3323 // Note that Transaction 1 was at /x/y/z, so this is in the same
3324 // protection space as digest.
3325 request.url = GURL("http://www.google.com/x/y/a/b");
3326 request.load_flags = 0;
3327
3328 MockWrite data_writes1[] = {
3329 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3330 "Host: www.google.com\r\n"
3331 "Connection: keep-alive\r\n"
3332 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3333 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3334 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3335 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3336 };
3337
3338 // Sever accepts the authorization.
3339 MockRead data_reads1[] = {
3340 MockRead("HTTP/1.0 200 OK\r\n"),
3341 MockRead("Content-Length: 100\r\n\r\n"),
3342 MockRead(false, OK),
3343 };
3344
3345 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3346 data_writes1, arraysize(data_writes1));
3347 session_deps.socket_factory.AddSocketDataProvider(&data1);
3348
3349 TestCompletionCallback callback1;
3350
3351 int rv = trans->Start(&request, &callback1, BoundNetLog());
3352 EXPECT_EQ(ERR_IO_PENDING, rv);
3353
3354 rv = callback1.WaitForResult();
3355 EXPECT_EQ(OK, rv);
3356
3357 const HttpResponseInfo* response = trans->GetResponseInfo();
3358 ASSERT_FALSE(response == NULL);
3359 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3360 }
3361}
3362
[email protected]89ceba9a2009-03-21 03:46:063363// Test the ResetStateForRestart() private method.
3364TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3365 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593366 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403367 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433368 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063369
3370 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063371 trans->read_buf_ = new IOBuffer(15);
3372 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573373 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063374
3375 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143376 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573377 response->auth_challenge = new AuthChallengeInfo();
3378 response->ssl_info.cert_status = -15;
3379 response->response_time = base::Time::Now();
3380 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063381
3382 { // Setup state for response_.vary_data
3383 HttpRequestInfo request;
3384 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3385 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573386 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433387 request.extra_headers.SetHeader("Foo", "1");
3388 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573389 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063390 }
3391
3392 // Cause the above state to be reset.
3393 trans->ResetStateForRestart();
3394
3395 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073396 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063397 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573398 EXPECT_EQ(0U, trans->request_headers_.size());
3399 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3400 EXPECT_TRUE(response->headers.get() == NULL);
3401 EXPECT_EQ(false, response->was_cached);
3402 EXPECT_EQ(0, response->ssl_info.cert_status);
3403 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063404}
3405
[email protected]bacff652009-03-31 17:50:333406// Test HTTPS connections to a site with a bad certificate
3407TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593408 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403409 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433410 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333411
3412 HttpRequestInfo request;
3413 request.method = "GET";
3414 request.url = GURL("https://www.google.com/");
3415 request.load_flags = 0;
3416
3417 MockWrite data_writes[] = {
3418 MockWrite("GET / HTTP/1.1\r\n"
3419 "Host: www.google.com\r\n"
3420 "Connection: keep-alive\r\n\r\n"),
3421 };
3422
3423 MockRead data_reads[] = {
3424 MockRead("HTTP/1.0 200 OK\r\n"),
3425 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3426 MockRead("Content-Length: 100\r\n\r\n"),
3427 MockRead(false, OK),
3428 };
3429
[email protected]5ecc992a42009-11-11 01:41:593430 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393431 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3432 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593433 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3434 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333435
[email protected]5ecc992a42009-11-11 01:41:593436 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3437 session_deps.socket_factory.AddSocketDataProvider(&data);
3438 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3439 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333440
3441 TestCompletionCallback callback;
3442
[email protected]5a1d7ca2010-04-28 20:12:273443 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333444 EXPECT_EQ(ERR_IO_PENDING, rv);
3445
3446 rv = callback.WaitForResult();
3447 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3448
3449 rv = trans->RestartIgnoringLastError(&callback);
3450 EXPECT_EQ(ERR_IO_PENDING, rv);
3451
3452 rv = callback.WaitForResult();
3453 EXPECT_EQ(OK, rv);
3454
3455 const HttpResponseInfo* response = trans->GetResponseInfo();
3456
3457 EXPECT_FALSE(response == NULL);
3458 EXPECT_EQ(100, response->headers->GetContentLength());
3459}
3460
3461// Test HTTPS connections to a site with a bad certificate, going through a
3462// proxy
3463TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593464 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333465
3466 HttpRequestInfo request;
3467 request.method = "GET";
3468 request.url = GURL("https://www.google.com/");
3469 request.load_flags = 0;
3470
3471 MockWrite proxy_writes[] = {
3472 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453473 "Host: www.google.com\r\n"
3474 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333475 };
3476
3477 MockRead proxy_reads[] = {
3478 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423479 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333480 };
3481
3482 MockWrite data_writes[] = {
3483 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453484 "Host: www.google.com\r\n"
3485 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333486 MockWrite("GET / HTTP/1.1\r\n"
3487 "Host: www.google.com\r\n"
3488 "Connection: keep-alive\r\n\r\n"),
3489 };
3490
3491 MockRead data_reads[] = {
3492 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3493 MockRead("HTTP/1.0 200 OK\r\n"),
3494 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3495 MockRead("Content-Length: 100\r\n\r\n"),
3496 MockRead(false, OK),
3497 };
3498
[email protected]31a2bfe2010-02-09 08:03:393499 StaticSocketDataProvider ssl_bad_certificate(
3500 proxy_reads, arraysize(proxy_reads),
3501 proxy_writes, arraysize(proxy_writes));
3502 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3503 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593504 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3505 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333506
[email protected]5ecc992a42009-11-11 01:41:593507 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3508 session_deps.socket_factory.AddSocketDataProvider(&data);
3509 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3510 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333511
3512 TestCompletionCallback callback;
3513
3514 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593515 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333516
[email protected]d207a5f2009-06-04 05:28:403517 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433518 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333519
[email protected]5a1d7ca2010-04-28 20:12:273520 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333521 EXPECT_EQ(ERR_IO_PENDING, rv);
3522
3523 rv = callback.WaitForResult();
3524 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3525
3526 rv = trans->RestartIgnoringLastError(&callback);
3527 EXPECT_EQ(ERR_IO_PENDING, rv);
3528
3529 rv = callback.WaitForResult();
3530 EXPECT_EQ(OK, rv);
3531
3532 const HttpResponseInfo* response = trans->GetResponseInfo();
3533
3534 EXPECT_FALSE(response == NULL);
3535 EXPECT_EQ(100, response->headers->GetContentLength());
3536 }
3537}
3538
[email protected]1c773ea12009-04-28 19:58:423539TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:593540 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403541 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433542 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423543
3544 HttpRequestInfo request;
3545 request.method = "GET";
3546 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433547 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3548 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:423549
3550 MockWrite data_writes[] = {
3551 MockWrite("GET / HTTP/1.1\r\n"
3552 "Host: www.google.com\r\n"
3553 "Connection: keep-alive\r\n"
3554 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3555 };
3556
3557 // Lastly, the server responds with the actual content.
3558 MockRead data_reads[] = {
3559 MockRead("HTTP/1.0 200 OK\r\n"),
3560 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3561 MockRead("Content-Length: 100\r\n\r\n"),
3562 MockRead(false, OK),
3563 };
3564
[email protected]31a2bfe2010-02-09 08:03:393565 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3566 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593567 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423568
3569 TestCompletionCallback callback;
3570
[email protected]5a1d7ca2010-04-28 20:12:273571 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423572 EXPECT_EQ(ERR_IO_PENDING, rv);
3573
3574 rv = callback.WaitForResult();
3575 EXPECT_EQ(OK, rv);
3576}
3577
3578TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593579 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403580 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433581 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423582
3583 HttpRequestInfo request;
3584 request.method = "GET";
3585 request.url = GURL("http://www.google.com/");
3586 request.load_flags = 0;
3587 request.referrer = GURL("http://the.previous.site.com/");
3588
3589 MockWrite data_writes[] = {
3590 MockWrite("GET / HTTP/1.1\r\n"
3591 "Host: www.google.com\r\n"
3592 "Connection: keep-alive\r\n"
3593 "Referer: http://the.previous.site.com/\r\n\r\n"),
3594 };
3595
3596 // Lastly, the server responds with the actual content.
3597 MockRead data_reads[] = {
3598 MockRead("HTTP/1.0 200 OK\r\n"),
3599 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3600 MockRead("Content-Length: 100\r\n\r\n"),
3601 MockRead(false, OK),
3602 };
3603
[email protected]31a2bfe2010-02-09 08:03:393604 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3605 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593606 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423607
3608 TestCompletionCallback callback;
3609
[email protected]5a1d7ca2010-04-28 20:12:273610 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423611 EXPECT_EQ(ERR_IO_PENDING, rv);
3612
3613 rv = callback.WaitForResult();
3614 EXPECT_EQ(OK, rv);
3615}
3616
3617TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593618 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403619 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433620 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423621
3622 HttpRequestInfo request;
3623 request.method = "POST";
3624 request.url = GURL("http://www.google.com/");
3625
3626 MockWrite data_writes[] = {
3627 MockWrite("POST / HTTP/1.1\r\n"
3628 "Host: www.google.com\r\n"
3629 "Connection: keep-alive\r\n"
3630 "Content-Length: 0\r\n\r\n"),
3631 };
3632
3633 // Lastly, the server responds with the actual content.
3634 MockRead data_reads[] = {
3635 MockRead("HTTP/1.0 200 OK\r\n"),
3636 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3637 MockRead("Content-Length: 100\r\n\r\n"),
3638 MockRead(false, OK),
3639 };
3640
[email protected]31a2bfe2010-02-09 08:03:393641 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3642 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593643 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423644
3645 TestCompletionCallback callback;
3646
[email protected]5a1d7ca2010-04-28 20:12:273647 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423648 EXPECT_EQ(ERR_IO_PENDING, rv);
3649
3650 rv = callback.WaitForResult();
3651 EXPECT_EQ(OK, rv);
3652}
3653
3654TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593655 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403656 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433657 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423658
3659 HttpRequestInfo request;
3660 request.method = "PUT";
3661 request.url = GURL("http://www.google.com/");
3662
3663 MockWrite data_writes[] = {
3664 MockWrite("PUT / HTTP/1.1\r\n"
3665 "Host: www.google.com\r\n"
3666 "Connection: keep-alive\r\n"
3667 "Content-Length: 0\r\n\r\n"),
3668 };
3669
3670 // Lastly, the server responds with the actual content.
3671 MockRead data_reads[] = {
3672 MockRead("HTTP/1.0 200 OK\r\n"),
3673 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3674 MockRead("Content-Length: 100\r\n\r\n"),
3675 MockRead(false, OK),
3676 };
3677
[email protected]31a2bfe2010-02-09 08:03:393678 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3679 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593680 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423681
3682 TestCompletionCallback callback;
3683
[email protected]5a1d7ca2010-04-28 20:12:273684 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423685 EXPECT_EQ(ERR_IO_PENDING, rv);
3686
3687 rv = callback.WaitForResult();
3688 EXPECT_EQ(OK, rv);
3689}
3690
3691TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593692 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403693 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433694 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423695
3696 HttpRequestInfo request;
3697 request.method = "HEAD";
3698 request.url = GURL("http://www.google.com/");
3699
3700 MockWrite data_writes[] = {
3701 MockWrite("HEAD / HTTP/1.1\r\n"
3702 "Host: www.google.com\r\n"
3703 "Connection: keep-alive\r\n"
3704 "Content-Length: 0\r\n\r\n"),
3705 };
3706
3707 // Lastly, the server responds with the actual content.
3708 MockRead data_reads[] = {
3709 MockRead("HTTP/1.0 200 OK\r\n"),
3710 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3711 MockRead("Content-Length: 100\r\n\r\n"),
3712 MockRead(false, OK),
3713 };
3714
[email protected]31a2bfe2010-02-09 08:03:393715 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3716 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593717 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423718
3719 TestCompletionCallback callback;
3720
[email protected]5a1d7ca2010-04-28 20:12:273721 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423722 EXPECT_EQ(ERR_IO_PENDING, rv);
3723
3724 rv = callback.WaitForResult();
3725 EXPECT_EQ(OK, rv);
3726}
3727
3728TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593729 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403730 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433731 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423732
3733 HttpRequestInfo request;
3734 request.method = "GET";
3735 request.url = GURL("http://www.google.com/");
3736 request.load_flags = LOAD_BYPASS_CACHE;
3737
3738 MockWrite data_writes[] = {
3739 MockWrite("GET / HTTP/1.1\r\n"
3740 "Host: www.google.com\r\n"
3741 "Connection: keep-alive\r\n"
3742 "Pragma: no-cache\r\n"
3743 "Cache-Control: no-cache\r\n\r\n"),
3744 };
3745
3746 // Lastly, the server responds with the actual content.
3747 MockRead data_reads[] = {
3748 MockRead("HTTP/1.0 200 OK\r\n"),
3749 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3750 MockRead("Content-Length: 100\r\n\r\n"),
3751 MockRead(false, OK),
3752 };
3753
[email protected]31a2bfe2010-02-09 08:03:393754 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3755 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593756 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423757
3758 TestCompletionCallback callback;
3759
[email protected]5a1d7ca2010-04-28 20:12:273760 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423761 EXPECT_EQ(ERR_IO_PENDING, rv);
3762
3763 rv = callback.WaitForResult();
3764 EXPECT_EQ(OK, rv);
3765}
3766
3767TEST_F(HttpNetworkTransactionTest,
3768 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:593769 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403770 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433771 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423772
3773 HttpRequestInfo request;
3774 request.method = "GET";
3775 request.url = GURL("http://www.google.com/");
3776 request.load_flags = LOAD_VALIDATE_CACHE;
3777
3778 MockWrite data_writes[] = {
3779 MockWrite("GET / HTTP/1.1\r\n"
3780 "Host: www.google.com\r\n"
3781 "Connection: keep-alive\r\n"
3782 "Cache-Control: max-age=0\r\n\r\n"),
3783 };
3784
3785 // Lastly, the server responds with the actual content.
3786 MockRead data_reads[] = {
3787 MockRead("HTTP/1.0 200 OK\r\n"),
3788 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3789 MockRead("Content-Length: 100\r\n\r\n"),
3790 MockRead(false, OK),
3791 };
3792
[email protected]31a2bfe2010-02-09 08:03:393793 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3794 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593795 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423796
3797 TestCompletionCallback callback;
3798
[email protected]5a1d7ca2010-04-28 20:12:273799 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423800 EXPECT_EQ(ERR_IO_PENDING, rv);
3801
3802 rv = callback.WaitForResult();
3803 EXPECT_EQ(OK, rv);
3804}
3805
3806TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593807 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403808 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433809 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423810
3811 HttpRequestInfo request;
3812 request.method = "GET";
3813 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433814 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423815
3816 MockWrite data_writes[] = {
3817 MockWrite("GET / HTTP/1.1\r\n"
3818 "Host: www.google.com\r\n"
3819 "Connection: keep-alive\r\n"
3820 "FooHeader: Bar\r\n\r\n"),
3821 };
3822
3823 // Lastly, the server responds with the actual content.
3824 MockRead data_reads[] = {
3825 MockRead("HTTP/1.0 200 OK\r\n"),
3826 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3827 MockRead("Content-Length: 100\r\n\r\n"),
3828 MockRead(false, OK),
3829 };
3830
[email protected]31a2bfe2010-02-09 08:03:393831 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3832 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593833 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423834
3835 TestCompletionCallback callback;
3836
[email protected]5a1d7ca2010-04-28 20:12:273837 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423838 EXPECT_EQ(ERR_IO_PENDING, rv);
3839
3840 rv = callback.WaitForResult();
3841 EXPECT_EQ(OK, rv);
3842}
3843
[email protected]270c6412010-03-29 22:02:473844TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3845 SessionDependencies session_deps;
3846 scoped_ptr<HttpTransaction> trans(
3847 new HttpNetworkTransaction(CreateSession(&session_deps)));
3848
3849 HttpRequestInfo request;
3850 request.method = "GET";
3851 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433852 request.extra_headers.SetHeader("referer", "www.foo.com");
3853 request.extra_headers.SetHeader("hEllo", "Kitty");
3854 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473855
3856 MockWrite data_writes[] = {
3857 MockWrite("GET / HTTP/1.1\r\n"
3858 "Host: www.google.com\r\n"
3859 "Connection: keep-alive\r\n"
3860 "hEllo: Kitty\r\n"
3861 "FoO: bar\r\n\r\n"),
3862 };
3863
3864 // Lastly, the server responds with the actual content.
3865 MockRead data_reads[] = {
3866 MockRead("HTTP/1.0 200 OK\r\n"),
3867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3868 MockRead("Content-Length: 100\r\n\r\n"),
3869 MockRead(false, OK),
3870 };
3871
3872 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3873 data_writes, arraysize(data_writes));
3874 session_deps.socket_factory.AddSocketDataProvider(&data);
3875
3876 TestCompletionCallback callback;
3877
[email protected]5a1d7ca2010-04-28 20:12:273878 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473879 EXPECT_EQ(ERR_IO_PENDING, rv);
3880
3881 rv = callback.WaitForResult();
3882 EXPECT_EQ(OK, rv);
3883}
3884
[email protected]3cd17242009-06-23 02:59:023885TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093886 SessionDependencies session_deps(
3887 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023888
3889 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433890 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023891
3892 HttpRequestInfo request;
3893 request.method = "GET";
3894 request.url = GURL("http://www.google.com/");
3895 request.load_flags = 0;
3896
3897 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3898 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3899
3900 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353901 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023902 MockWrite("GET / HTTP/1.1\r\n"
3903 "Host: www.google.com\r\n"
3904 "Connection: keep-alive\r\n\r\n")
3905 };
3906
3907 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593908 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023909 MockRead("HTTP/1.0 200 OK\r\n"),
3910 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3911 MockRead("Payload"),
3912 MockRead(false, OK)
3913 };
3914
[email protected]31a2bfe2010-02-09 08:03:393915 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3916 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593917 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023918
3919 TestCompletionCallback callback;
3920
[email protected]5a1d7ca2010-04-28 20:12:273921 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023922 EXPECT_EQ(ERR_IO_PENDING, rv);
3923
3924 rv = callback.WaitForResult();
3925 EXPECT_EQ(OK, rv);
3926
3927 const HttpResponseInfo* response = trans->GetResponseInfo();
3928 EXPECT_FALSE(response == NULL);
3929
3930 std::string response_text;
3931 rv = ReadTransaction(trans.get(), &response_text);
3932 EXPECT_EQ(OK, rv);
3933 EXPECT_EQ("Payload", response_text);
3934}
3935
3936TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093937 SessionDependencies session_deps(
3938 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023939
3940 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433941 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023942
3943 HttpRequestInfo request;
3944 request.method = "GET";
3945 request.url = GURL("https://www.google.com/");
3946 request.load_flags = 0;
3947
3948 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3949 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3950
3951 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353952 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3953 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023954 MockWrite("GET / HTTP/1.1\r\n"
3955 "Host: www.google.com\r\n"
3956 "Connection: keep-alive\r\n\r\n")
3957 };
3958
3959 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353960 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3961 arraysize(read_buffer)),
3962 MockRead("HTTP/1.0 200 OK\r\n"),
3963 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3964 MockRead("Payload"),
3965 MockRead(false, OK)
3966 };
3967
[email protected]31a2bfe2010-02-09 08:03:393968 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3969 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593970 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:353971
[email protected]5ecc992a42009-11-11 01:41:593972 SSLSocketDataProvider ssl(true, OK);
3973 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:353974
3975 TestCompletionCallback callback;
3976
[email protected]5a1d7ca2010-04-28 20:12:273977 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:353978 EXPECT_EQ(ERR_IO_PENDING, rv);
3979
3980 rv = callback.WaitForResult();
3981 EXPECT_EQ(OK, rv);
3982
3983 const HttpResponseInfo* response = trans->GetResponseInfo();
3984 EXPECT_FALSE(response == NULL);
3985
3986 std::string response_text;
3987 rv = ReadTransaction(trans.get(), &response_text);
3988 EXPECT_EQ(OK, rv);
3989 EXPECT_EQ("Payload", response_text);
3990}
3991
3992TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093993 SessionDependencies session_deps(
3994 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:353995
3996 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433997 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:353998
3999 HttpRequestInfo request;
4000 request.method = "GET";
4001 request.url = GURL("http://www.google.com/");
4002 request.load_flags = 0;
4003
4004 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4005 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374006 const char kSOCKS5OkRequest[] = {
4007 0x05, // Version
4008 0x01, // Command (CONNECT)
4009 0x00, // Reserved.
4010 0x03, // Address type (DOMAINNAME).
4011 0x0E, // Length of domain (14)
4012 // Domain string:
4013 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4014 0x00, 0x50, // 16-bit port (80)
4015 };
[email protected]e0c27be2009-07-15 13:09:354016 const char kSOCKS5OkResponse[] =
4017 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4018
4019 MockWrite data_writes[] = {
4020 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4021 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4022 MockWrite("GET / HTTP/1.1\r\n"
4023 "Host: www.google.com\r\n"
4024 "Connection: keep-alive\r\n\r\n")
4025 };
4026
4027 MockRead data_reads[] = {
4028 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4029 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4030 MockRead("HTTP/1.0 200 OK\r\n"),
4031 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4032 MockRead("Payload"),
4033 MockRead(false, OK)
4034 };
4035
[email protected]31a2bfe2010-02-09 08:03:394036 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4037 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594038 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354039
4040 TestCompletionCallback callback;
4041
[email protected]5a1d7ca2010-04-28 20:12:274042 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354043 EXPECT_EQ(ERR_IO_PENDING, rv);
4044
4045 rv = callback.WaitForResult();
4046 EXPECT_EQ(OK, rv);
4047
4048 const HttpResponseInfo* response = trans->GetResponseInfo();
4049 EXPECT_FALSE(response == NULL);
4050
4051 std::string response_text;
4052 rv = ReadTransaction(trans.get(), &response_text);
4053 EXPECT_EQ(OK, rv);
4054 EXPECT_EQ("Payload", response_text);
4055}
4056
4057TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094058 SessionDependencies session_deps(
4059 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354060
4061 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434062 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354063
4064 HttpRequestInfo request;
4065 request.method = "GET";
4066 request.url = GURL("https://www.google.com/");
4067 request.load_flags = 0;
4068
4069 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4070 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374071 const unsigned char kSOCKS5OkRequest[] = {
4072 0x05, // Version
4073 0x01, // Command (CONNECT)
4074 0x00, // Reserved.
4075 0x03, // Address type (DOMAINNAME).
4076 0x0E, // Length of domain (14)
4077 // Domain string:
4078 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4079 0x01, 0xBB, // 16-bit port (443)
4080 };
4081
[email protected]e0c27be2009-07-15 13:09:354082 const char kSOCKS5OkResponse[] =
4083 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4084
4085 MockWrite data_writes[] = {
4086 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4087 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4088 arraysize(kSOCKS5OkRequest)),
4089 MockWrite("GET / HTTP/1.1\r\n"
4090 "Host: www.google.com\r\n"
4091 "Connection: keep-alive\r\n\r\n")
4092 };
4093
4094 MockRead data_reads[] = {
4095 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4096 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024097 MockRead("HTTP/1.0 200 OK\r\n"),
4098 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4099 MockRead("Payload"),
4100 MockRead(false, OK)
4101 };
4102
[email protected]31a2bfe2010-02-09 08:03:394103 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4104 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594105 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024106
[email protected]5ecc992a42009-11-11 01:41:594107 SSLSocketDataProvider ssl(true, OK);
4108 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024109
4110 TestCompletionCallback callback;
4111
[email protected]5a1d7ca2010-04-28 20:12:274112 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024113 EXPECT_EQ(ERR_IO_PENDING, rv);
4114
4115 rv = callback.WaitForResult();
4116 EXPECT_EQ(OK, rv);
4117
4118 const HttpResponseInfo* response = trans->GetResponseInfo();
4119 EXPECT_FALSE(response == NULL);
4120
4121 std::string response_text;
4122 rv = ReadTransaction(trans.get(), &response_text);
4123 EXPECT_EQ(OK, rv);
4124 EXPECT_EQ("Payload", response_text);
4125}
4126
[email protected]04e5be32009-06-26 20:00:314127// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064128
4129struct GroupNameTest {
4130 std::string proxy_server;
4131 std::string url;
4132 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184133 bool ssl;
[email protected]2d731a32010-04-29 01:04:064134};
4135
4136scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4137 const std::string& proxy_server) {
4138 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4139 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4140
4141 HttpAlternateProtocols* alternate_protocols =
4142 session->mutable_alternate_protocols();
4143 alternate_protocols->SetAlternateProtocolFor(
4144 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354145 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064146
4147 return session;
4148}
4149
4150int GroupNameTransactionHelper(
4151 const std::string& url,
4152 const scoped_refptr<HttpNetworkSession>& session) {
4153 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4154
4155 HttpRequestInfo request;
4156 request.method = "GET";
4157 request.url = GURL(url);
4158 request.load_flags = 0;
4159
4160 TestCompletionCallback callback;
4161
4162 // We do not complete this request, the dtor will clean the transaction up.
4163 return trans->Start(&request, &callback, BoundNetLog());
4164}
4165
4166TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4167 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314168 {
[email protected]2d731a32010-04-29 01:04:064169 "", // unused
[email protected]04e5be32009-06-26 20:00:314170 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544171 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184172 false,
[email protected]2ff8b312010-04-26 22:20:544173 },
4174 {
[email protected]2d731a32010-04-29 01:04:064175 "", // unused
[email protected]2ff8b312010-04-26 22:20:544176 "http://[2001:1418:13:1::25]/direct",
4177 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184178 false,
[email protected]04e5be32009-06-26 20:00:314179 },
[email protected]04e5be32009-06-26 20:00:314180
4181 // SSL Tests
4182 {
[email protected]2d731a32010-04-29 01:04:064183 "", // unused
[email protected]04e5be32009-06-26 20:00:314184 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024185 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184186 true,
[email protected]04e5be32009-06-26 20:00:314187 },
4188 {
[email protected]2d731a32010-04-29 01:04:064189 "", // unused
4190 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024191 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184192 true,
[email protected]04e5be32009-06-26 20:00:314193 },
4194 {
[email protected]2d731a32010-04-29 01:04:064195 "", // unused
[email protected]2ff8b312010-04-26 22:20:544196 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024197 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184198 true,
[email protected]2ff8b312010-04-26 22:20:544199 },
[email protected]2d731a32010-04-29 01:04:064200 };
[email protected]2ff8b312010-04-26 22:20:544201
[email protected]2d731a32010-04-29 01:04:064202 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4203
4204 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4205 scoped_refptr<HttpNetworkSession> session(
4206 SetupSessionForGroupNameTests(tests[i].proxy_server));
4207
4208 HttpNetworkSessionPeer peer(session);
4209 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4210 new CaptureGroupNameTCPSocketPool(session.get()));
4211 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184212 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4213 new CaptureGroupNameSSLSocketPool(session.get()));
4214 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064215
4216 EXPECT_EQ(ERR_IO_PENDING,
4217 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184218 if (tests[i].ssl)
4219 EXPECT_EQ(tests[i].expected_group_name,
4220 ssl_conn_pool->last_group_name_received());
4221 else
4222 EXPECT_EQ(tests[i].expected_group_name,
4223 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064224 }
4225
4226 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4227}
4228
4229TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4230 const GroupNameTest tests[] = {
4231 {
4232 "http_proxy",
4233 "http://www.google.com/http_proxy_normal",
4234 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184235 false,
[email protected]2d731a32010-04-29 01:04:064236 },
4237
4238 // SSL Tests
4239 {
4240 "http_proxy",
4241 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024242 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184243 true,
[email protected]2d731a32010-04-29 01:04:064244 },
4245
[email protected]9faeded92010-04-29 20:03:054246 {
4247 "http_proxy",
4248 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024249 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184250 true,
[email protected]9faeded92010-04-29 20:03:054251 },
[email protected]2d731a32010-04-29 01:04:064252 };
4253
4254 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4255
4256 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4257 scoped_refptr<HttpNetworkSession> session(
4258 SetupSessionForGroupNameTests(tests[i].proxy_server));
4259
4260 HttpNetworkSessionPeer peer(session);
4261
[email protected]e60e47a2010-07-14 03:37:184262 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134263 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4264 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184265 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4266 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4267 new CaptureGroupNameSSLSocketPool(session.get()));
4268 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064269
4270 EXPECT_EQ(ERR_IO_PENDING,
4271 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184272 if (tests[i].ssl)
4273 EXPECT_EQ(tests[i].expected_group_name,
4274 ssl_conn_pool->last_group_name_received());
4275 else
4276 EXPECT_EQ(tests[i].expected_group_name,
4277 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064278 }
4279
4280 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4281}
4282
4283TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4284 const GroupNameTest tests[] = {
4285 {
4286 "socks4://socks_proxy:1080",
4287 "http://www.google.com/socks4_direct",
4288 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184289 false,
[email protected]2d731a32010-04-29 01:04:064290 },
4291 {
4292 "socks5://socks_proxy:1080",
4293 "http://www.google.com/socks5_direct",
4294 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184295 false,
[email protected]2d731a32010-04-29 01:04:064296 },
4297
4298 // SSL Tests
4299 {
4300 "socks4://socks_proxy:1080",
4301 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024302 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184303 true,
[email protected]2d731a32010-04-29 01:04:064304 },
4305 {
4306 "socks5://socks_proxy:1080",
4307 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024308 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184309 true,
[email protected]2d731a32010-04-29 01:04:064310 },
4311
[email protected]9faeded92010-04-29 20:03:054312 {
4313 "socks4://socks_proxy:1080",
4314 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024315 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184316 true,
[email protected]9faeded92010-04-29 20:03:054317 },
[email protected]04e5be32009-06-26 20:00:314318 };
4319
[email protected]2ff8b312010-04-26 22:20:544320 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4321
[email protected]04e5be32009-06-26 20:00:314322 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064323 scoped_refptr<HttpNetworkSession> session(
4324 SetupSessionForGroupNameTests(tests[i].proxy_server));
4325 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314326
[email protected]e60e47a2010-07-14 03:37:184327 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264328 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064329 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184330 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4331 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4332 new CaptureGroupNameSSLSocketPool(session.get()));
4333 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314334
[email protected]5695b8c2009-09-30 21:36:434335 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314336
[email protected]2d731a32010-04-29 01:04:064337 EXPECT_EQ(ERR_IO_PENDING,
4338 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184339 if (tests[i].ssl)
4340 EXPECT_EQ(tests[i].expected_group_name,
4341 ssl_conn_pool->last_group_name_received());
4342 else
4343 EXPECT_EQ(tests[i].expected_group_name,
4344 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314345 }
[email protected]2ff8b312010-04-26 22:20:544346
4347 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314348}
4349
[email protected]9172a982009-06-06 00:30:254350TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544351 SessionDependencies session_deps(
4352 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324353
[email protected]69719062010-01-05 20:09:214354 // This simulates failure resolving all hostnames; that means we will fail
4355 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324356 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4357
[email protected]9172a982009-06-06 00:30:254358 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434359 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254360
4361 HttpRequestInfo request;
4362 request.method = "GET";
4363 request.url = GURL("http://www.google.com/");
4364
4365 TestCompletionCallback callback;
4366
[email protected]5a1d7ca2010-04-28 20:12:274367 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254368 EXPECT_EQ(ERR_IO_PENDING, rv);
4369
[email protected]9172a982009-06-06 00:30:254370 rv = callback.WaitForResult();
4371 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4372}
4373
[email protected]f3e6c1e2009-06-15 20:52:124374// Host resolution observer used by
4375// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4376// resovle requests are issued with a referrer of |expected_referrer|.
4377class ResolutionReferrerObserver : public HostResolver::Observer {
4378 public:
4379 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4380 : expected_referrer_(expected_referrer),
4381 called_start_with_referrer_(false),
4382 called_finish_with_referrer_(false) {
4383 }
4384
4385 virtual void OnStartResolution(int id,
4386 const HostResolver::RequestInfo& info) {
4387 if (info.referrer() == expected_referrer_)
4388 called_start_with_referrer_ = true;
4389 }
4390
4391 virtual void OnFinishResolutionWithStatus(
4392 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4393 if (info.referrer() == expected_referrer_)
4394 called_finish_with_referrer_ = true;
4395 }
4396
[email protected]eb255d32009-06-17 02:11:034397 virtual void OnCancelResolution(int id,
4398 const HostResolver::RequestInfo& info ) {
4399 FAIL() << "Should not be cancelling any requests!";
4400 }
4401
[email protected]f3e6c1e2009-06-15 20:52:124402 bool did_complete_with_expected_referrer() const {
4403 return called_start_with_referrer_ && called_finish_with_referrer_;
4404 }
4405
4406 private:
4407 GURL expected_referrer_;
4408 bool called_start_with_referrer_;
4409 bool called_finish_with_referrer_;
4410
4411 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4412};
4413
4414// Make sure that when HostResolver::Resolve() is invoked, it passes through
4415// the "referrer". This is depended on by the DNS prefetch observer.
4416TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4417 GURL referrer = GURL("http://expected-referrer/");
4418 EXPECT_TRUE(referrer.is_valid());
4419 ResolutionReferrerObserver resolution_observer(referrer);
4420
4421 SessionDependencies session_deps;
4422 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434423 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124424
4425 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144426 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124427
4428 // Connect up a mock socket which will fail when reading.
4429 MockRead data_reads[] = {
4430 MockRead(false, ERR_FAILED),
4431 };
[email protected]31a2bfe2010-02-09 08:03:394432 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594433 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124434
4435 // Issue a request, containing an HTTP referrer.
4436 HttpRequestInfo request;
4437 request.method = "GET";
4438 request.referrer = referrer;
4439 request.url = GURL("http://www.google.com/");
4440
4441 // Run the request until it fails reading from the socket.
4442 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274443 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124444 EXPECT_EQ(ERR_IO_PENDING, rv);
4445 rv = callback.WaitForResult();
4446 EXPECT_EQ(ERR_FAILED, rv);
4447
4448 // Check that the host resolution observer saw |referrer|.
4449 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4450}
4451
[email protected]685af592010-05-11 19:31:244452// Base test to make sure that when the load flags for a request specify to
4453// bypass the cache, the DNS cache is not used.
4454void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284455 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324456
[email protected]a2c2fb92009-07-18 07:31:044457 // Select a host resolver that does caching.
4458 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324459
[email protected]3b9cca42009-06-16 01:08:284460 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434461 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284462
4463 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4464 // a synchronous lookup.)
4465 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144466 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464467 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274468 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284469 EXPECT_EQ(OK, rv);
4470
4471 // Verify that it was added to host cache, by doing a subsequent async lookup
4472 // and confirming it completes synchronously.
4473 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464474 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284475 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274476 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324477 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284478
4479 // Inject a failure the next time that "www.google.com" is resolved. This way
4480 // we can tell if the next lookup hit the cache, or the "network".
4481 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324482 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284483
4484 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4485 // first read -- this won't be reached as the host resolution will fail first.
4486 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394487 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594488 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284489
4490 // Issue a request, asking to bypass the cache(s).
4491 HttpRequestInfo request;
4492 request.method = "GET";
[email protected]685af592010-05-11 19:31:244493 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284494 request.url = GURL("http://www.google.com/");
4495
4496 // Run the request.
4497 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274498 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284499 ASSERT_EQ(ERR_IO_PENDING, rv);
4500 rv = callback.WaitForResult();
4501
4502 // If we bypassed the cache, we would have gotten a failure while resolving
4503 // "www.google.com".
4504 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4505}
4506
[email protected]685af592010-05-11 19:31:244507// There are multiple load flags that should trigger the host cache bypass.
4508// Test each in isolation:
4509TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4510 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4511}
4512
4513TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4514 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4515}
4516
4517TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4518 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4519}
4520
[email protected]0877e3d2009-10-17 22:29:574521// Make sure we can handle an error when writing the request.
4522TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4523 SessionDependencies session_deps;
4524 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4525
4526 HttpRequestInfo request;
4527 request.method = "GET";
4528 request.url = GURL("http://www.foo.com/");
4529 request.load_flags = 0;
4530
4531 MockWrite write_failure[] = {
4532 MockWrite(true, ERR_CONNECTION_RESET),
4533 };
[email protected]31a2bfe2010-02-09 08:03:394534 StaticSocketDataProvider data(NULL, 0,
4535 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594536 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574537
4538 TestCompletionCallback callback;
4539
4540 scoped_ptr<HttpTransaction> trans(
4541 new HttpNetworkTransaction(CreateSession(&session_deps)));
4542
[email protected]5a1d7ca2010-04-28 20:12:274543 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574544 EXPECT_EQ(ERR_IO_PENDING, rv);
4545
4546 rv = callback.WaitForResult();
4547 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4548}
4549
4550// Check that a connection closed after the start of the headers finishes ok.
4551TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4552 SessionDependencies session_deps;
4553 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4554
4555 HttpRequestInfo request;
4556 request.method = "GET";
4557 request.url = GURL("http://www.foo.com/");
4558 request.load_flags = 0;
4559
4560 MockRead data_reads[] = {
4561 MockRead("HTTP/1."),
4562 MockRead(false, OK),
4563 };
4564
[email protected]31a2bfe2010-02-09 08:03:394565 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594566 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574567
4568 TestCompletionCallback callback;
4569
4570 scoped_ptr<HttpTransaction> trans(
4571 new HttpNetworkTransaction(CreateSession(&session_deps)));
4572
[email protected]5a1d7ca2010-04-28 20:12:274573 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574574 EXPECT_EQ(ERR_IO_PENDING, rv);
4575
4576 rv = callback.WaitForResult();
4577 EXPECT_EQ(OK, rv);
4578
4579 const HttpResponseInfo* response = trans->GetResponseInfo();
4580 EXPECT_TRUE(response != NULL);
4581
4582 EXPECT_TRUE(response->headers != NULL);
4583 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4584
4585 std::string response_data;
4586 rv = ReadTransaction(trans.get(), &response_data);
4587 EXPECT_EQ(OK, rv);
4588 EXPECT_EQ("", response_data);
4589}
4590
4591// Make sure that a dropped connection while draining the body for auth
4592// restart does the right thing.
4593TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4594 SessionDependencies session_deps;
4595 scoped_ptr<HttpTransaction> trans(
4596 new HttpNetworkTransaction(CreateSession(&session_deps)));
4597
4598 HttpRequestInfo request;
4599 request.method = "GET";
4600 request.url = GURL("http://www.google.com/");
4601 request.load_flags = 0;
4602
4603 MockWrite data_writes1[] = {
4604 MockWrite("GET / HTTP/1.1\r\n"
4605 "Host: www.google.com\r\n"
4606 "Connection: keep-alive\r\n\r\n"),
4607 };
4608
4609 MockRead data_reads1[] = {
4610 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4611 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4612 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4613 MockRead("Content-Length: 14\r\n\r\n"),
4614 MockRead("Unauth"),
4615 MockRead(true, ERR_CONNECTION_RESET),
4616 };
4617
[email protected]31a2bfe2010-02-09 08:03:394618 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4619 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594620 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574621
4622 // After calling trans->RestartWithAuth(), this is the request we should
4623 // be issuing -- the final header line contains the credentials.
4624 MockWrite data_writes2[] = {
4625 MockWrite("GET / HTTP/1.1\r\n"
4626 "Host: www.google.com\r\n"
4627 "Connection: keep-alive\r\n"
4628 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4629 };
4630
4631 // Lastly, the server responds with the actual content.
4632 MockRead data_reads2[] = {
4633 MockRead("HTTP/1.1 200 OK\r\n"),
4634 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4635 MockRead("Content-Length: 100\r\n\r\n"),
4636 MockRead(false, OK),
4637 };
4638
[email protected]31a2bfe2010-02-09 08:03:394639 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4640 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594641 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574642
4643 TestCompletionCallback callback1;
4644
[email protected]5a1d7ca2010-04-28 20:12:274645 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574646 EXPECT_EQ(ERR_IO_PENDING, rv);
4647
4648 rv = callback1.WaitForResult();
4649 EXPECT_EQ(OK, rv);
4650
4651 const HttpResponseInfo* response = trans->GetResponseInfo();
4652 EXPECT_FALSE(response == NULL);
4653
4654 // The password prompt info should have been set in response->auth_challenge.
4655 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4656
4657 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4658 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4659 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4660
4661 TestCompletionCallback callback2;
4662
[email protected]13c8a092010-07-29 06:15:444663 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:574664 EXPECT_EQ(ERR_IO_PENDING, rv);
4665
4666 rv = callback2.WaitForResult();
4667 EXPECT_EQ(OK, rv);
4668
4669 response = trans->GetResponseInfo();
4670 EXPECT_FALSE(response == NULL);
4671 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4672 EXPECT_EQ(100, response->headers->GetContentLength());
4673}
4674
4675// Test HTTPS connections going through a proxy that sends extra data.
4676TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4677 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4678
4679 HttpRequestInfo request;
4680 request.method = "GET";
4681 request.url = GURL("https://www.google.com/");
4682 request.load_flags = 0;
4683
4684 MockRead proxy_reads[] = {
4685 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4686 MockRead(false, OK)
4687 };
4688
[email protected]31a2bfe2010-02-09 08:03:394689 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594690 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574691
[email protected]5ecc992a42009-11-11 01:41:594692 session_deps.socket_factory.AddSocketDataProvider(&data);
4693 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574694
4695 TestCompletionCallback callback;
4696
4697 session_deps.socket_factory.ResetNextMockIndexes();
4698
4699 scoped_ptr<HttpTransaction> trans(
4700 new HttpNetworkTransaction(CreateSession(&session_deps)));
4701
[email protected]5a1d7ca2010-04-28 20:12:274702 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574703 EXPECT_EQ(ERR_IO_PENDING, rv);
4704
4705 rv = callback.WaitForResult();
4706 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4707}
4708
[email protected]e22e1362009-11-23 21:31:124709TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464710 SessionDependencies session_deps;
4711 scoped_ptr<HttpTransaction> trans(
4712 new HttpNetworkTransaction(CreateSession(&session_deps)));
4713
4714 HttpRequestInfo request;
4715 request.method = "GET";
4716 request.url = GURL("http://www.google.com/");
4717 request.load_flags = 0;
4718
[email protected]e22e1362009-11-23 21:31:124719 MockRead data_reads[] = {
4720 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4721 MockRead(false, OK),
4722 };
[email protected]9492e4a2010-02-24 00:58:464723
4724 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4725 session_deps.socket_factory.AddSocketDataProvider(&data);
4726
4727 TestCompletionCallback callback;
4728
[email protected]5a1d7ca2010-04-28 20:12:274729 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464730 EXPECT_EQ(ERR_IO_PENDING, rv);
4731
4732 EXPECT_EQ(OK, callback.WaitForResult());
4733
4734 const HttpResponseInfo* response = trans->GetResponseInfo();
4735 EXPECT_TRUE(response != NULL);
4736
4737 EXPECT_TRUE(response->headers != NULL);
4738 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4739
4740 std::string response_data;
4741 rv = ReadTransaction(trans.get(), &response_data);
4742 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124743}
4744
[email protected]95d88ffe2010-02-04 21:25:334745TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4746 SessionDependencies session_deps;
4747 scoped_ptr<HttpTransaction> trans(
4748 new HttpNetworkTransaction(CreateSession(&session_deps)));
4749
4750 HttpRequestInfo request;
4751 request.method = "POST";
4752 request.url = GURL("http://www.google.com/upload");
4753 request.upload_data = new UploadData;
4754 request.load_flags = 0;
4755
4756 FilePath temp_file_path;
4757 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4758 const uint64 kFakeSize = 100000; // file is actually blank
4759
4760 std::vector<UploadData::Element> elements;
4761 UploadData::Element element;
4762 element.SetToFilePath(temp_file_path);
4763 element.SetContentLength(kFakeSize);
4764 elements.push_back(element);
4765 request.upload_data->set_elements(elements);
4766 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4767
4768 MockRead data_reads[] = {
4769 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4770 MockRead("hello world"),
4771 MockRead(false, OK),
4772 };
[email protected]31a2bfe2010-02-09 08:03:394773 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334774 session_deps.socket_factory.AddSocketDataProvider(&data);
4775
4776 TestCompletionCallback callback;
4777
[email protected]5a1d7ca2010-04-28 20:12:274778 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334779 EXPECT_EQ(ERR_IO_PENDING, rv);
4780
4781 rv = callback.WaitForResult();
4782 EXPECT_EQ(OK, rv);
4783
4784 const HttpResponseInfo* response = trans->GetResponseInfo();
4785 EXPECT_TRUE(response != NULL);
4786
4787 EXPECT_TRUE(response->headers != NULL);
4788 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4789
4790 std::string response_data;
4791 rv = ReadTransaction(trans.get(), &response_data);
4792 EXPECT_EQ(OK, rv);
4793 EXPECT_EQ("hello world", response_data);
4794
4795 file_util::Delete(temp_file_path, false);
4796}
4797
[email protected]6624b4622010-03-29 19:58:364798TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4799 // If we try to upload an unreadable file, the network stack should report
4800 // the file size as zero and upload zero bytes for that file.
4801 SessionDependencies session_deps;
4802 scoped_ptr<HttpTransaction> trans(
4803 new HttpNetworkTransaction(CreateSession(&session_deps)));
4804
4805 FilePath temp_file;
4806 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4807 std::string temp_file_content("Unreadable file.");
4808 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4809 temp_file_content.length()));
4810 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4811
4812 HttpRequestInfo request;
4813 request.method = "POST";
4814 request.url = GURL("http://www.google.com/upload");
4815 request.upload_data = new UploadData;
4816 request.load_flags = 0;
4817
4818 std::vector<UploadData::Element> elements;
4819 UploadData::Element element;
4820 element.SetToFilePath(temp_file);
4821 elements.push_back(element);
4822 request.upload_data->set_elements(elements);
4823
4824 MockRead data_reads[] = {
4825 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4826 MockRead(false, OK),
4827 };
4828 MockWrite data_writes[] = {
4829 MockWrite("POST /upload HTTP/1.1\r\n"
4830 "Host: www.google.com\r\n"
4831 "Connection: keep-alive\r\n"
4832 "Content-Length: 0\r\n\r\n"),
4833 MockWrite(false, OK),
4834 };
4835 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4836 arraysize(data_writes));
4837 session_deps.socket_factory.AddSocketDataProvider(&data);
4838
4839 TestCompletionCallback callback;
4840
[email protected]5a1d7ca2010-04-28 20:12:274841 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364842 EXPECT_EQ(ERR_IO_PENDING, rv);
4843
4844 rv = callback.WaitForResult();
4845 EXPECT_EQ(OK, rv);
4846
4847 const HttpResponseInfo* response = trans->GetResponseInfo();
4848 EXPECT_TRUE(response != NULL);
4849 EXPECT_TRUE(response->headers != NULL);
4850 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4851
4852 file_util::Delete(temp_file, false);
4853}
4854
4855TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4856 SessionDependencies session_deps;
4857 scoped_ptr<HttpTransaction> trans(
4858 new HttpNetworkTransaction(CreateSession(&session_deps)));
4859
4860 FilePath temp_file;
4861 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4862 std::string temp_file_contents("Unreadable file.");
4863 std::string unreadable_contents(temp_file_contents.length(), '\0');
4864 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4865 temp_file_contents.length()));
4866
4867 HttpRequestInfo request;
4868 request.method = "POST";
4869 request.url = GURL("http://www.google.com/upload");
4870 request.upload_data = new UploadData;
4871 request.load_flags = 0;
4872
4873 std::vector<UploadData::Element> elements;
4874 UploadData::Element element;
4875 element.SetToFilePath(temp_file);
4876 elements.push_back(element);
4877 request.upload_data->set_elements(elements);
4878
4879 MockRead data_reads[] = {
4880 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4881 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4882 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4883
4884 MockRead("HTTP/1.1 200 OK\r\n"),
4885 MockRead("Content-Length: 0\r\n\r\n"),
4886 MockRead(false, OK),
4887 };
4888 MockWrite data_writes[] = {
4889 MockWrite("POST /upload HTTP/1.1\r\n"
4890 "Host: www.google.com\r\n"
4891 "Connection: keep-alive\r\n"
4892 "Content-Length: 16\r\n\r\n"),
4893 MockWrite(false, temp_file_contents.c_str()),
4894
4895 MockWrite("POST /upload HTTP/1.1\r\n"
4896 "Host: www.google.com\r\n"
4897 "Connection: keep-alive\r\n"
4898 "Content-Length: 16\r\n"
4899 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4900 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4901 MockWrite(false, OK),
4902 };
4903 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4904 arraysize(data_writes));
4905 session_deps.socket_factory.AddSocketDataProvider(&data);
4906
4907 TestCompletionCallback callback1;
4908
[email protected]5a1d7ca2010-04-28 20:12:274909 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364910 EXPECT_EQ(ERR_IO_PENDING, rv);
4911
4912 rv = callback1.WaitForResult();
4913 EXPECT_EQ(OK, rv);
4914
4915 const HttpResponseInfo* response = trans->GetResponseInfo();
4916 EXPECT_TRUE(response != NULL);
4917 EXPECT_TRUE(response->headers != NULL);
4918 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4919
4920 // The password prompt info should have been set in response->auth_challenge.
4921 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4922 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4923 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4924 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4925
4926 // Now make the file unreadable and try again.
4927 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4928
4929 TestCompletionCallback callback2;
4930
[email protected]13c8a092010-07-29 06:15:444931 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:364932 EXPECT_EQ(ERR_IO_PENDING, rv);
4933
4934 rv = callback2.WaitForResult();
4935 EXPECT_EQ(OK, rv);
4936
4937 response = trans->GetResponseInfo();
4938 EXPECT_TRUE(response != NULL);
4939 EXPECT_TRUE(response->headers != NULL);
4940 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4941 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4942
4943 file_util::Delete(temp_file, false);
4944}
4945
[email protected]aeefc9e82010-02-19 16:18:274946// Tests that changes to Auth realms are treated like auth rejections.
4947TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4948 SessionDependencies session_deps;
4949 scoped_ptr<HttpTransaction> trans(
4950 new HttpNetworkTransaction(CreateSession(&session_deps)));
4951
4952 HttpRequestInfo request;
4953 request.method = "GET";
4954 request.url = GURL("http://www.google.com/");
4955 request.load_flags = 0;
4956
4957 // First transaction will request a resource and receive a Basic challenge
4958 // with realm="first_realm".
4959 MockWrite data_writes1[] = {
4960 MockWrite("GET / HTTP/1.1\r\n"
4961 "Host: www.google.com\r\n"
4962 "Connection: keep-alive\r\n"
4963 "\r\n"),
4964 };
4965 MockRead data_reads1[] = {
4966 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4967 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4968 "\r\n"),
4969 };
4970
4971 // After calling trans->RestartWithAuth(), provide an Authentication header
4972 // for first_realm. The server will reject and provide a challenge with
4973 // second_realm.
4974 MockWrite data_writes2[] = {
4975 MockWrite("GET / HTTP/1.1\r\n"
4976 "Host: www.google.com\r\n"
4977 "Connection: keep-alive\r\n"
4978 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
4979 "\r\n"),
4980 };
4981 MockRead data_reads2[] = {
4982 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4983 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
4984 "\r\n"),
4985 };
4986
4987 // This again fails, and goes back to first_realm. Make sure that the
4988 // entry is removed from cache.
4989 MockWrite data_writes3[] = {
4990 MockWrite("GET / HTTP/1.1\r\n"
4991 "Host: www.google.com\r\n"
4992 "Connection: keep-alive\r\n"
4993 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
4994 "\r\n"),
4995 };
4996 MockRead data_reads3[] = {
4997 MockRead("HTTP/1.1 401 Unauthorized\r\n"
4998 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
4999 "\r\n"),
5000 };
5001
5002 // Try one last time (with the correct password) and get the resource.
5003 MockWrite data_writes4[] = {
5004 MockWrite("GET / HTTP/1.1\r\n"
5005 "Host: www.google.com\r\n"
5006 "Connection: keep-alive\r\n"
5007 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5008 "\r\n"),
5009 };
5010 MockRead data_reads4[] = {
5011 MockRead("HTTP/1.1 200 OK\r\n"
5012 "Content-Type: text/html; charset=iso-8859-1\r\n"
5013 "Content-Length: 100\r\n"
5014 "\r\n"),
5015 };
5016
5017 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5018 data_writes1, arraysize(data_writes1));
5019 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5020 data_writes2, arraysize(data_writes2));
5021 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5022 data_writes3, arraysize(data_writes3));
5023 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5024 data_writes4, arraysize(data_writes4));
5025 session_deps.socket_factory.AddSocketDataProvider(&data1);
5026 session_deps.socket_factory.AddSocketDataProvider(&data2);
5027 session_deps.socket_factory.AddSocketDataProvider(&data3);
5028 session_deps.socket_factory.AddSocketDataProvider(&data4);
5029
5030 TestCompletionCallback callback1;
5031
5032 // Issue the first request with Authorize headers. There should be a
5033 // password prompt for first_realm waiting to be filled in after the
5034 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275035 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275036 EXPECT_EQ(ERR_IO_PENDING, rv);
5037 rv = callback1.WaitForResult();
5038 EXPECT_EQ(OK, rv);
5039 const HttpResponseInfo* response = trans->GetResponseInfo();
5040 ASSERT_FALSE(response == NULL);
5041 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5042 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5043 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5044 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5045
5046 // Issue the second request with an incorrect password. There should be a
5047 // password prompt for second_realm waiting to be filled in after the
5048 // transaction completes.
5049 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445050 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275051 EXPECT_EQ(ERR_IO_PENDING, rv);
5052 rv = callback2.WaitForResult();
5053 EXPECT_EQ(OK, rv);
5054 response = trans->GetResponseInfo();
5055 ASSERT_FALSE(response == NULL);
5056 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5057 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5058 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5059 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5060
5061 // Issue the third request with another incorrect password. There should be
5062 // a password prompt for first_realm waiting to be filled in. If the password
5063 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5064 // first_realm was not correctly removed.
5065 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445066 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275067 EXPECT_EQ(ERR_IO_PENDING, rv);
5068 rv = callback3.WaitForResult();
5069 EXPECT_EQ(OK, rv);
5070 response = trans->GetResponseInfo();
5071 ASSERT_FALSE(response == NULL);
5072 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5073 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5074 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5075 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5076
5077 // Issue the fourth request with the correct password and username.
5078 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445079 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275080 EXPECT_EQ(ERR_IO_PENDING, rv);
5081 rv = callback4.WaitForResult();
5082 EXPECT_EQ(OK, rv);
5083 response = trans->GetResponseInfo();
5084 ASSERT_FALSE(response == NULL);
5085 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5086}
5087
[email protected]564b4912010-03-09 16:30:425088TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:425089 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:065090 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:425091
[email protected]564b4912010-03-09 16:30:425092 SessionDependencies session_deps;
5093
5094 MockRead data_reads[] = {
5095 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355096 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425097 MockRead("hello world"),
5098 MockRead(false, OK),
5099 };
5100
5101 HttpRequestInfo request;
5102 request.method = "GET";
5103 request.url = GURL("http://www.google.com/");
5104 request.load_flags = 0;
5105
5106 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5107
5108 session_deps.socket_factory.AddSocketDataProvider(&data);
5109
5110 TestCompletionCallback callback;
5111
5112 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5113 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5114
[email protected]5a1d7ca2010-04-28 20:12:275115 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425116 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535117
[email protected]2fbaecf22010-07-22 22:20:355118 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425119 const HttpAlternateProtocols& alternate_protocols =
5120 session->alternate_protocols();
5121 EXPECT_FALSE(
5122 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5123
5124 EXPECT_EQ(OK, callback.WaitForResult());
5125
5126 const HttpResponseInfo* response = trans->GetResponseInfo();
5127 ASSERT_TRUE(response != NULL);
5128 ASSERT_TRUE(response->headers != NULL);
5129 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535130 EXPECT_FALSE(response->was_fetched_via_spdy);
5131 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575132 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425133
5134 std::string response_data;
5135 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5136 EXPECT_EQ("hello world", response_data);
5137
5138 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5139 const HttpAlternateProtocols::PortProtocolPair alternate =
5140 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5141 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5142 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355143 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425144 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425145
[email protected]31e2c69e2010-04-15 18:06:065146 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:425147 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:425148}
5149
5150TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:065151 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:425152 SessionDependencies session_deps;
5153
5154 HttpRequestInfo request;
5155 request.method = "GET";
5156 request.url = GURL("http://www.google.com/");
5157 request.load_flags = 0;
5158
5159 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5160 StaticSocketDataProvider first_data;
5161 first_data.set_connect_data(mock_connect);
5162 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5163
5164 MockRead data_reads[] = {
5165 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5166 MockRead("hello world"),
5167 MockRead(true, OK),
5168 };
5169 StaticSocketDataProvider second_data(
5170 data_reads, arraysize(data_reads), NULL, 0);
5171 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5172
5173 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5174 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5175 // http://crbug.com/37454.
5176 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5177
5178 TestCompletionCallback callback;
5179
5180 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5181
[email protected]2fbaecf22010-07-22 22:20:355182 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425183 HttpAlternateProtocols* alternate_protocols =
5184 session->mutable_alternate_protocols();
5185 alternate_protocols->SetAlternateProtocolFor(
5186 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355187 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425188
5189 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5190
[email protected]5a1d7ca2010-04-28 20:12:275191 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425192 EXPECT_EQ(ERR_IO_PENDING, rv);
5193 EXPECT_EQ(OK, callback.WaitForResult());
5194
5195 const HttpResponseInfo* response = trans->GetResponseInfo();
5196 ASSERT_TRUE(response != NULL);
5197 ASSERT_TRUE(response->headers != NULL);
5198 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5199
5200 std::string response_data;
5201 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5202 EXPECT_EQ("hello world", response_data);
5203
5204 ASSERT_TRUE(
5205 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5206 const HttpAlternateProtocols::PortProtocolPair alternate =
5207 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5208 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065209 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425210}
5211
5212// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5213// says that it does SPDY, but it just does the TLS handshake, but the NPN
5214// response does not indicate SPDY, so we just do standard HTTPS over the port.
5215// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5216// on the original port.
[email protected]a2cb8122010-03-10 17:22:425217// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5218// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535219//
[email protected]a2cb8122010-03-10 17:22:425220// HttpRequestInfo request;
5221// request.method = "GET";
5222// request.url = GURL("http://www.google.com/");
5223// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535224//
[email protected]a2cb8122010-03-10 17:22:425225// MockRead data_reads[] = {
5226// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5227// MockRead("hello world"),
5228// MockRead(true, OK),
5229// };
5230// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5231// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535232//
[email protected]a2cb8122010-03-10 17:22:425233// SSLSocketDataProvider ssl(true, OK);
5234// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535235//
[email protected]a2cb8122010-03-10 17:22:425236// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535237//
[email protected]a2cb8122010-03-10 17:22:425238// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535239//
[email protected]a2cb8122010-03-10 17:22:425240// HostPortPair http_host_port_pair;
5241// http_host_port_pair.host = "www.google.com";
5242// http_host_port_pair.port = 80;
5243// HttpAlternateProtocols* alternate_protocols =
5244// session->mutable_alternate_protocols();
5245// alternate_protocols->SetAlternateProtocolFor(
5246// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065247// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535248//
[email protected]a2cb8122010-03-10 17:22:425249// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535250//
[email protected]5a1d7ca2010-04-28 20:12:275251// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425252// EXPECT_EQ(ERR_IO_PENDING, rv);
5253// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535254//
[email protected]a2cb8122010-03-10 17:22:425255// const HttpResponseInfo* response = trans->GetResponseInfo();
5256// ASSERT_TRUE(response != NULL);
5257// ASSERT_TRUE(response->headers != NULL);
5258// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535259//
[email protected]a2cb8122010-03-10 17:22:425260// std::string response_data;
5261// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5262// EXPECT_EQ("hello world", response_data);
5263// }
5264
5265TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065266 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355267 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425268 SessionDependencies session_deps;
5269
5270 HttpRequestInfo request;
5271 request.method = "GET";
5272 request.url = GURL("http://www.google.com/");
5273 request.load_flags = 0;
5274
[email protected]a2cb8122010-03-10 17:22:425275 StaticSocketDataProvider first_tcp_connect;
5276 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5277
5278 SSLSocketDataProvider ssl(true, OK);
5279 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5280
[email protected]564b4912010-03-09 16:30:425281 MockRead data_reads[] = {
5282 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5283 MockRead("hello world"),
5284 MockRead(true, OK),
5285 };
[email protected]a2cb8122010-03-10 17:22:425286 StaticSocketDataProvider fallback_data(
5287 data_reads, arraysize(data_reads), NULL, 0);
5288 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425289
5290 TestCompletionCallback callback;
5291
5292 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5293
[email protected]2fbaecf22010-07-22 22:20:355294 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425295 HttpAlternateProtocols* alternate_protocols =
5296 session->mutable_alternate_protocols();
5297 alternate_protocols->SetAlternateProtocolFor(
5298 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355299 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425300
5301 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5302
[email protected]5a1d7ca2010-04-28 20:12:275303 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425304 EXPECT_EQ(ERR_IO_PENDING, rv);
5305 EXPECT_EQ(OK, callback.WaitForResult());
5306
5307 const HttpResponseInfo* response = trans->GetResponseInfo();
5308 ASSERT_TRUE(response != NULL);
5309 ASSERT_TRUE(response->headers != NULL);
5310 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5311
5312 std::string response_data;
5313 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5314 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545315 HttpNetworkTransaction::SetNextProtos("");
5316 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5317}
5318
5319TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5320 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355321 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545322 SessionDependencies session_deps;
5323
5324 HttpRequestInfo request;
5325 request.method = "GET";
5326 request.url = GURL("http://www.google.com/");
5327 request.load_flags = 0;
5328
5329 MockRead data_reads[] = {
5330 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355331 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545332 MockRead("hello world"),
5333 MockRead(true, OK),
5334 };
5335
5336 StaticSocketDataProvider first_transaction(
5337 data_reads, arraysize(data_reads), NULL, 0);
5338 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5339
5340 SSLSocketDataProvider ssl(true, OK);
5341 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355342 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535343 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545344 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5345
[email protected]2bd93022010-07-17 00:58:445346 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135347 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545348
[email protected]2bd93022010-07-17 00:58:445349 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5350 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545351 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135352 CreateMockRead(*resp),
5353 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545354 MockRead(true, 0, 0),
5355 };
5356
5357 scoped_refptr<DelayedSocketData> spdy_data(
5358 new DelayedSocketData(
5359 1, // wait for one write to finish before reading.
5360 spdy_reads, arraysize(spdy_reads),
5361 spdy_writes, arraysize(spdy_writes)));
5362 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5363
5364 TestCompletionCallback callback;
5365
5366 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5367 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5368
[email protected]5a1d7ca2010-04-28 20:12:275369 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545370 EXPECT_EQ(ERR_IO_PENDING, rv);
5371 EXPECT_EQ(OK, callback.WaitForResult());
5372
5373 const HttpResponseInfo* response = trans->GetResponseInfo();
5374 ASSERT_TRUE(response != NULL);
5375 ASSERT_TRUE(response->headers != NULL);
5376 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5377
5378 std::string response_data;
5379 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5380 EXPECT_EQ("hello world", response_data);
5381
5382 trans.reset(new HttpNetworkTransaction(session));
5383
[email protected]5a1d7ca2010-04-28 20:12:275384 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545385 EXPECT_EQ(ERR_IO_PENDING, rv);
5386 EXPECT_EQ(OK, callback.WaitForResult());
5387
5388 response = trans->GetResponseInfo();
5389 ASSERT_TRUE(response != NULL);
5390 ASSERT_TRUE(response->headers != NULL);
5391 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535392 EXPECT_TRUE(response->was_fetched_via_spdy);
5393 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575394 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545395
5396 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5397 EXPECT_EQ("hello!", response_data);
5398
5399 HttpNetworkTransaction::SetNextProtos("");
5400 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5401}
5402
[email protected]631f1322010-04-30 17:59:115403class CapturingProxyResolver : public ProxyResolver {
5404 public:
5405 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5406 virtual ~CapturingProxyResolver() {}
5407
5408 virtual int GetProxyForURL(const GURL& url,
5409 ProxyInfo* results,
5410 CompletionCallback* callback,
5411 RequestHandle* request,
5412 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:405413 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
5414 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:425415 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115416 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425417 return OK;
[email protected]631f1322010-04-30 17:59:115418 }
5419
5420 virtual void CancelRequest(RequestHandle request) {
5421 NOTREACHED();
5422 }
5423
[email protected]24476402010-07-20 20:55:175424 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:115425 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425426 return OK;
[email protected]631f1322010-04-30 17:59:115427 }
5428
[email protected]24476402010-07-20 20:55:175429 const std::vector<GURL>& resolved() const { return resolved_; }
5430
5431 private:
[email protected]631f1322010-04-30 17:59:115432 std::vector<GURL> resolved_;
5433
5434 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5435};
5436
[email protected]631f1322010-04-30 17:59:115437TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5438 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355439 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:115440
5441 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425442 proxy_config.set_auto_detect(true);
5443 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115444
[email protected]631f1322010-04-30 17:59:115445 CapturingProxyResolver* capturing_proxy_resolver =
5446 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385447 SessionDependencies session_deps(new ProxyService(
5448 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5449 NULL));
[email protected]631f1322010-04-30 17:59:115450
5451 HttpRequestInfo request;
5452 request.method = "GET";
5453 request.url = GURL("http://www.google.com/");
5454 request.load_flags = 0;
5455
5456 MockRead data_reads[] = {
5457 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355458 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:115459 MockRead("hello world"),
5460 MockRead(true, OK),
5461 };
5462
5463 StaticSocketDataProvider first_transaction(
5464 data_reads, arraysize(data_reads), NULL, 0);
5465 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5466
5467 SSLSocketDataProvider ssl(true, OK);
5468 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355469 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535470 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115471 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5472
[email protected]2bd93022010-07-17 00:58:445473 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:115474 MockWrite spdy_writes[] = {
5475 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5476 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425477 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135478 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115479 };
5480
[email protected]d911f1b2010-05-05 22:39:425481 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5482
[email protected]2bd93022010-07-17 00:58:445483 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5484 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:115485 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425486 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135487 CreateMockRead(*resp.get(), 4), // 2, 4
5488 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425489 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115490 };
5491
[email protected]d911f1b2010-05-05 22:39:425492 scoped_refptr<OrderedSocketData> spdy_data(
5493 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115494 spdy_reads, arraysize(spdy_reads),
5495 spdy_writes, arraysize(spdy_writes)));
5496 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5497
5498 TestCompletionCallback callback;
5499
5500 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5501 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5502
5503 int rv = trans->Start(&request, &callback, BoundNetLog());
5504 EXPECT_EQ(ERR_IO_PENDING, rv);
5505 EXPECT_EQ(OK, callback.WaitForResult());
5506
5507 const HttpResponseInfo* response = trans->GetResponseInfo();
5508 ASSERT_TRUE(response != NULL);
5509 ASSERT_TRUE(response->headers != NULL);
5510 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535511 EXPECT_FALSE(response->was_fetched_via_spdy);
5512 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115513
5514 std::string response_data;
5515 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5516 EXPECT_EQ("hello world", response_data);
5517
5518 trans.reset(new HttpNetworkTransaction(session));
5519
5520 rv = trans->Start(&request, &callback, BoundNetLog());
5521 EXPECT_EQ(ERR_IO_PENDING, rv);
5522 EXPECT_EQ(OK, callback.WaitForResult());
5523
5524 response = trans->GetResponseInfo();
5525 ASSERT_TRUE(response != NULL);
5526 ASSERT_TRUE(response->headers != NULL);
5527 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535528 EXPECT_TRUE(response->was_fetched_via_spdy);
5529 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115530
5531 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5532 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425533 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5534 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115535 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425536 EXPECT_EQ("https://www.google.com/",
5537 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115538
5539 HttpNetworkTransaction::SetNextProtos("");
5540 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5541}
[email protected]631f1322010-04-30 17:59:115542
[email protected]2ff8b312010-04-26 22:20:545543TEST_F(HttpNetworkTransactionTest,
5544 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5545 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355546 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545547 SessionDependencies session_deps;
5548
5549 HttpRequestInfo request;
5550 request.method = "GET";
5551 request.url = GURL("http://www.google.com/");
5552 request.load_flags = 0;
5553
5554 MockRead data_reads[] = {
5555 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355556 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545557 MockRead("hello world"),
5558 MockRead(true, OK),
5559 };
5560
5561 StaticSocketDataProvider first_transaction(
5562 data_reads, arraysize(data_reads), NULL, 0);
5563 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5564
5565 SSLSocketDataProvider ssl(true, OK);
5566 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355567 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535568 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545569 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535570 // Make sure we use ssl for spdy here.
5571 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545572
[email protected]2bd93022010-07-17 00:58:445573 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135574 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545575
[email protected]2bd93022010-07-17 00:58:445576 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5577 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545578 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135579 CreateMockRead(*resp),
5580 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545581 MockRead(true, 0, 0),
5582 };
5583
5584 scoped_refptr<DelayedSocketData> spdy_data(
5585 new DelayedSocketData(
5586 1, // wait for one write to finish before reading.
5587 spdy_reads, arraysize(spdy_reads),
5588 spdy_writes, arraysize(spdy_writes)));
5589 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5590
5591 TestCompletionCallback callback;
5592
5593 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5594
5595 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5596
[email protected]5a1d7ca2010-04-28 20:12:275597 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545598 EXPECT_EQ(ERR_IO_PENDING, rv);
5599 EXPECT_EQ(OK, callback.WaitForResult());
5600
5601 const HttpResponseInfo* response = trans->GetResponseInfo();
5602 ASSERT_TRUE(response != NULL);
5603 ASSERT_TRUE(response->headers != NULL);
5604 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5605
5606 std::string response_data;
5607 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5608 EXPECT_EQ("hello world", response_data);
5609
5610 // Set up an initial SpdySession in the pool to reuse.
[email protected]b261d0e2010-08-02 19:13:245611 HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT");
[email protected]2ff8b312010-04-26 22:20:545612 scoped_refptr<SpdySession> spdy_session =
[email protected]b261d0e2010-08-02 19:13:245613 session->spdy_session_pool()->Get(pair, session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215614 scoped_refptr<TCPSocketParams> tcp_params =
5615 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365616 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545617 trans.reset(new HttpNetworkTransaction(session));
5618
[email protected]5a1d7ca2010-04-28 20:12:275619 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545620 EXPECT_EQ(ERR_IO_PENDING, rv);
5621 EXPECT_EQ(OK, callback.WaitForResult());
5622
5623 response = trans->GetResponseInfo();
5624 ASSERT_TRUE(response != NULL);
5625 ASSERT_TRUE(response->headers != NULL);
5626 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535627 EXPECT_TRUE(response->was_fetched_via_spdy);
5628 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575629 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545630
5631 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5632 EXPECT_EQ("hello!", response_data);
5633
5634 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065635 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425636}
5637
[email protected]044de0642010-06-17 10:42:155638// GenerateAuthToken is a mighty big test.
5639// It tests all permutation of GenerateAuthToken behavior:
5640// - Synchronous and Asynchronous completion.
5641// - OK or error on completion.
5642// - Direct connection, non-authenticating proxy, and authenticating proxy.
5643// - HTTP or HTTPS backend (to include proxy tunneling).
5644// - Non-authenticating and authenticating backend.
5645//
5646// In all, there are 44 reasonable permuations (for example, if there are
5647// problems generating an auth token for an authenticating proxy, we don't
5648// need to test all permutations of the backend server).
5649//
5650// The test proceeds by going over each of the configuration cases, and
5651// potentially running up to three rounds in each of the tests. The TestConfig
5652// specifies both the configuration for the test as well as the expectations
5653// for the results.
5654TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5655 const char* kServer = "http://www.example.com";
5656 const char* kSecureServer = "https://www.example.com";
5657 const char* kProxy = "myproxy:70";
5658 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5659
5660 enum AuthTiming {
5661 AUTH_NONE,
5662 AUTH_SYNC,
5663 AUTH_ASYNC,
5664 };
5665
5666 const MockWrite kGet(
5667 "GET / HTTP/1.1\r\n"
5668 "Host: www.example.com\r\n"
5669 "Connection: keep-alive\r\n\r\n");
5670 const MockWrite kGetProxy(
5671 "GET http://www.example.com/ HTTP/1.1\r\n"
5672 "Host: www.example.com\r\n"
5673 "Proxy-Connection: keep-alive\r\n\r\n");
5674 const MockWrite kGetAuth(
5675 "GET / HTTP/1.1\r\n"
5676 "Host: www.example.com\r\n"
5677 "Connection: keep-alive\r\n"
5678 "Authorization: auth_token\r\n\r\n");
5679 const MockWrite kGetProxyAuth(
5680 "GET http://www.example.com/ HTTP/1.1\r\n"
5681 "Host: www.example.com\r\n"
5682 "Proxy-Connection: keep-alive\r\n"
5683 "Proxy-Authorization: auth_token\r\n\r\n");
5684 const MockWrite kGetAuthThroughProxy(
5685 "GET http://www.example.com/ HTTP/1.1\r\n"
5686 "Host: www.example.com\r\n"
5687 "Proxy-Connection: keep-alive\r\n"
5688 "Authorization: auth_token\r\n\r\n");
5689 const MockWrite kGetAuthWithProxyAuth(
5690 "GET http://www.example.com/ HTTP/1.1\r\n"
5691 "Host: www.example.com\r\n"
5692 "Proxy-Connection: keep-alive\r\n"
5693 "Proxy-Authorization: auth_token\r\n"
5694 "Authorization: auth_token\r\n\r\n");
5695 const MockWrite kConnect(
5696 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5697 "Host: www.example.com\r\n"
5698 "Proxy-Connection: keep-alive\r\n\r\n");
5699 const MockWrite kConnectProxyAuth(
5700 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5701 "Host: www.example.com\r\n"
5702 "Proxy-Connection: keep-alive\r\n"
5703 "Proxy-Authorization: auth_token\r\n\r\n");
5704
5705 const MockRead kSuccess(
5706 "HTTP/1.1 200 OK\r\n"
5707 "Content-Type: text/html; charset=iso-8859-1\r\n"
5708 "Content-Length: 3\r\n\r\n"
5709 "Yes");
5710 const MockRead kFailure(
5711 "Should not be called.");
5712 const MockRead kServerChallenge(
5713 "HTTP/1.1 401 Unauthorized\r\n"
5714 "WWW-Authenticate: Mock realm=server\r\n"
5715 "Content-Type: text/html; charset=iso-8859-1\r\n"
5716 "Content-Length: 14\r\n\r\n"
5717 "Unauthorized\r\n");
5718 const MockRead kProxyChallenge(
5719 "HTTP/1.1 407 Unauthorized\r\n"
5720 "Proxy-Authenticate: Mock realm=proxy\r\n"
5721 "Proxy-Connection: close\r\n"
5722 "Content-Type: text/html; charset=iso-8859-1\r\n"
5723 "Content-Length: 14\r\n\r\n"
5724 "Unauthorized\r\n");
5725 const MockRead kProxyConnected(
5726 "HTTP/1.1 200 Connection Established\r\n\r\n");
5727
5728 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5729 // no constructors, but the C++ compiler on Windows warns about
5730 // unspecified data in compound literals. So, moved to using constructors,
5731 // and TestRound's created with the default constructor should not be used.
5732 struct TestRound {
5733 TestRound()
5734 : expected_rv(ERR_UNEXPECTED),
5735 extra_write(NULL),
5736 extra_read(NULL) {
5737 }
5738 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5739 int expected_rv_arg)
5740 : write(write_arg),
5741 read(read_arg),
5742 expected_rv(expected_rv_arg),
5743 extra_write(NULL),
5744 extra_read(NULL) {
5745 }
5746 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5747 int expected_rv_arg, const MockWrite* extra_write_arg,
5748 const MockWrite* extra_read_arg)
5749 : write(write_arg),
5750 read(read_arg),
5751 expected_rv(expected_rv_arg),
5752 extra_write(extra_write_arg),
5753 extra_read(extra_read_arg) {
5754 }
5755 MockWrite write;
5756 MockRead read;
5757 int expected_rv;
5758 const MockWrite* extra_write;
5759 const MockRead* extra_read;
5760 };
5761
5762 static const int kNoSSL = 500;
5763
5764 struct TestConfig {
5765 const char* proxy_url;
5766 AuthTiming proxy_auth_timing;
5767 int proxy_auth_rv;
5768 const char* server_url;
5769 AuthTiming server_auth_timing;
5770 int server_auth_rv;
5771 int num_auth_rounds;
5772 int first_ssl_round;
5773 TestRound rounds[3];
5774 } test_configs[] = {
5775 // Non-authenticating HTTP server with a direct connection.
5776 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5777 { TestRound(kGet, kSuccess, OK)}},
5778 // Authenticating HTTP server with a direct connection.
5779 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5780 { TestRound(kGet, kServerChallenge, OK),
5781 TestRound(kGetAuth, kSuccess, OK)}},
5782 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5783 { TestRound(kGet, kServerChallenge, OK),
5784 TestRound(kGetAuth, kFailure, kAuthErr)}},
5785 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5786 { TestRound(kGet, kServerChallenge, OK),
5787 TestRound(kGetAuth, kSuccess, OK)}},
5788 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5789 { TestRound(kGet, kServerChallenge, OK),
5790 TestRound(kGetAuth, kFailure, kAuthErr)}},
5791 // Non-authenticating HTTP server through a non-authenticating proxy.
5792 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5793 { TestRound(kGetProxy, kSuccess, OK)}},
5794 // Authenticating HTTP server through a non-authenticating proxy.
5795 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5796 { TestRound(kGetProxy, kServerChallenge, OK),
5797 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5798 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5799 { TestRound(kGetProxy, kServerChallenge, OK),
5800 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5801 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5802 { TestRound(kGetProxy, kServerChallenge, OK),
5803 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5804 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5805 { TestRound(kGetProxy, kServerChallenge, OK),
5806 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5807 // Non-authenticating HTTP server through an authenticating proxy.
5808 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5809 { TestRound(kGetProxy, kProxyChallenge, OK),
5810 TestRound(kGetProxyAuth, kSuccess, OK)}},
5811 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5812 { TestRound(kGetProxy, kProxyChallenge, OK),
5813 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5814 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5815 { TestRound(kGetProxy, kProxyChallenge, OK),
5816 TestRound(kGetProxyAuth, kSuccess, OK)}},
5817 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5818 { TestRound(kGetProxy, kProxyChallenge, OK),
5819 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5820 // Authenticating HTTP server through an authenticating proxy.
5821 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5822 { TestRound(kGetProxy, kProxyChallenge, OK),
5823 TestRound(kGetProxyAuth, kServerChallenge, OK),
5824 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5825 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5826 { TestRound(kGetProxy, kProxyChallenge, OK),
5827 TestRound(kGetProxyAuth, kServerChallenge, OK),
5828 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5829 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5830 { TestRound(kGetProxy, kProxyChallenge, OK),
5831 TestRound(kGetProxyAuth, kServerChallenge, OK),
5832 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5833 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5834 { TestRound(kGetProxy, kProxyChallenge, OK),
5835 TestRound(kGetProxyAuth, kServerChallenge, OK),
5836 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5837 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5838 { TestRound(kGetProxy, kProxyChallenge, OK),
5839 TestRound(kGetProxyAuth, kServerChallenge, OK),
5840 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5841 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5842 { TestRound(kGetProxy, kProxyChallenge, OK),
5843 TestRound(kGetProxyAuth, kServerChallenge, OK),
5844 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5845 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5846 { TestRound(kGetProxy, kProxyChallenge, OK),
5847 TestRound(kGetProxyAuth, kServerChallenge, OK),
5848 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5849 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5850 { TestRound(kGetProxy, kProxyChallenge, OK),
5851 TestRound(kGetProxyAuth, kServerChallenge, OK),
5852 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5853 // Non-authenticating HTTPS server with a direct connection.
5854 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5855 { TestRound(kGet, kSuccess, OK)}},
5856 // Authenticating HTTPS server with a direct connection.
5857 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5858 { TestRound(kGet, kServerChallenge, OK),
5859 TestRound(kGetAuth, kSuccess, OK)}},
5860 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5861 { TestRound(kGet, kServerChallenge, OK),
5862 TestRound(kGetAuth, kFailure, kAuthErr)}},
5863 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5864 { TestRound(kGet, kServerChallenge, OK),
5865 TestRound(kGetAuth, kSuccess, OK)}},
5866 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5867 { TestRound(kGet, kServerChallenge, OK),
5868 TestRound(kGetAuth, kFailure, kAuthErr)}},
5869 // Non-authenticating HTTPS server with a non-authenticating proxy.
5870 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5871 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5872 // Authenticating HTTPS server through a non-authenticating proxy.
5873 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5874 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5875 TestRound(kGetAuth, kSuccess, OK)}},
5876 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5877 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5878 TestRound(kGetAuth, kFailure, kAuthErr)}},
5879 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5880 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5881 TestRound(kGetAuth, kSuccess, OK)}},
5882 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5883 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5884 TestRound(kGetAuth, kFailure, kAuthErr)}},
5885 // Non-Authenticating HTTPS server through an authenticating proxy.
5886 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5887 { TestRound(kConnect, kProxyChallenge, OK),
5888 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5889 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5890 { TestRound(kConnect, kProxyChallenge, OK),
5891 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5892 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5893 { TestRound(kConnect, kProxyChallenge, OK),
5894 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5895 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5896 { TestRound(kConnect, kProxyChallenge, OK),
5897 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5898 // Authenticating HTTPS server through an authenticating proxy.
5899 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5900 { TestRound(kConnect, kProxyChallenge, OK),
5901 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5902 &kGet, &kServerChallenge),
5903 TestRound(kGetAuth, kSuccess, OK)}},
5904 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5905 { TestRound(kConnect, kProxyChallenge, OK),
5906 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5907 &kGet, &kServerChallenge),
5908 TestRound(kGetAuth, kFailure, kAuthErr)}},
5909 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5910 { TestRound(kConnect, kProxyChallenge, OK),
5911 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5912 &kGet, &kServerChallenge),
5913 TestRound(kGetAuth, kSuccess, OK)}},
5914 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5915 { TestRound(kConnect, kProxyChallenge, OK),
5916 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5917 &kGet, &kServerChallenge),
5918 TestRound(kGetAuth, kFailure, kAuthErr)}},
5919 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5920 { TestRound(kConnect, kProxyChallenge, OK),
5921 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5922 &kGet, &kServerChallenge),
5923 TestRound(kGetAuth, kSuccess, OK)}},
5924 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5925 { TestRound(kConnect, kProxyChallenge, OK),
5926 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5927 &kGet, &kServerChallenge),
5928 TestRound(kGetAuth, kFailure, kAuthErr)}},
5929 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5930 { TestRound(kConnect, kProxyChallenge, OK),
5931 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5932 &kGet, &kServerChallenge),
5933 TestRound(kGetAuth, kSuccess, OK)}},
5934 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5935 { TestRound(kConnect, kProxyChallenge, OK),
5936 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5937 &kGet, &kServerChallenge),
5938 TestRound(kGetAuth, kFailure, kAuthErr)}},
5939 };
5940
5941 SessionDependencies session_deps;
5942 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005943 HttpAuthHandlerMock::Factory* auth_factory(
5944 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155945 session_deps.http_auth_handler_factory.reset(auth_factory);
5946
5947 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5948 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:265949
5950 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:155951 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005952 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155953 std::string auth_challenge = "Mock realm=proxy";
5954 GURL origin(test_config.proxy_url);
5955 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5956 auth_challenge.end());
5957 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5958 origin, BoundNetLog());
5959 auth_handler->SetGenerateExpectation(
5960 test_config.proxy_auth_timing == AUTH_ASYNC,
5961 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:155962 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
5963 }
5964 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005965 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155966 std::string auth_challenge = "Mock realm=server";
5967 GURL origin(test_config.server_url);
5968 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5969 auth_challenge.end());
5970 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
5971 origin, BoundNetLog());
5972 auth_handler->SetGenerateExpectation(
5973 test_config.server_auth_timing == AUTH_ASYNC,
5974 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:155975 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
5976 }
5977 if (test_config.proxy_url) {
5978 session_deps.proxy_service =
5979 CreateFixedProxyService(test_config.proxy_url);
5980 } else {
5981 session_deps.proxy_service = ProxyService::CreateNull();
5982 }
5983
5984 HttpRequestInfo request;
5985 request.method = "GET";
5986 request.url = GURL(test_config.server_url);
5987 request.load_flags = 0;
5988
5989 scoped_ptr<HttpTransaction> trans(
5990 new HttpNetworkTransaction(CreateSession(&session_deps)));
5991
5992 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
5993 const TestRound& read_write_round = test_config.rounds[round];
5994
5995 // Set up expected reads and writes.
5996 MockRead reads[2];
5997 reads[0] = read_write_round.read;
5998 size_t length_reads = 1;
5999 if (read_write_round.extra_read) {
6000 reads[1] = *read_write_round.extra_read;
6001 length_reads = 2;
6002 }
6003
6004 MockWrite writes[2];
6005 writes[0] = read_write_round.write;
6006 size_t length_writes = 1;
6007 if (read_write_round.extra_write) {
6008 writes[1] = *read_write_round.extra_write;
6009 length_writes = 2;
6010 }
6011 StaticSocketDataProvider data_provider(
6012 reads, length_reads, writes, length_writes);
6013 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6014
6015 // Add an SSL sequence if necessary.
6016 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6017 if (round >= test_config.first_ssl_round)
6018 session_deps.socket_factory.AddSSLSocketDataProvider(
6019 &ssl_socket_data_provider);
6020
6021 // Start or restart the transaction.
6022 TestCompletionCallback callback;
6023 int rv;
6024 if (round == 0) {
6025 rv = trans->Start(&request, &callback, BoundNetLog());
6026 } else {
[email protected]13c8a092010-07-29 06:15:446027 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156028 }
6029 if (rv == ERR_IO_PENDING)
6030 rv = callback.WaitForResult();
6031
6032 // Compare results with expected data.
6033 EXPECT_EQ(read_write_round.expected_rv, rv);
6034 const HttpResponseInfo* response = trans->GetResponseInfo();
6035 if (read_write_round.expected_rv == OK) {
6036 EXPECT_FALSE(response == NULL);
6037 } else {
6038 EXPECT_TRUE(response == NULL);
6039 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6040 continue;
6041 }
6042 if (round + 1 < test_config.num_auth_rounds) {
6043 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6044 } else {
6045 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6046 }
6047 }
[email protected]e5ae96a2010-04-14 20:12:456048 }
[email protected]e60e47a2010-07-14 03:37:186049
6050 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
6051 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:456052}
6053
[email protected]c871bce92010-07-15 21:51:146054TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6055 // Do multi-round authentication and make sure it works correctly.
6056 SessionDependencies session_deps;
6057 HttpAuthHandlerMock::Factory* auth_factory(
6058 new HttpAuthHandlerMock::Factory());
6059 session_deps.http_auth_handler_factory.reset(auth_factory);
6060 session_deps.proxy_service = ProxyService::CreateNull();
6061 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6062 session_deps.host_resolver->set_synchronous_mode(true);
6063
6064 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6065 auth_handler->set_connection_based(true);
6066 std::string auth_challenge = "Mock realm=server";
6067 GURL origin("http://www.example.com");
6068 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6069 auth_challenge.end());
6070 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6071 origin, BoundNetLog());
6072 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6073
6074 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6075 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6076
6077 int rv = OK;
6078 const HttpResponseInfo* response = NULL;
6079 HttpRequestInfo request;
6080 request.method = "GET";
6081 request.url = origin;
6082 request.load_flags = 0;
6083 TestCompletionCallback callback;
6084
6085 const MockWrite kGet(
6086 "GET / HTTP/1.1\r\n"
6087 "Host: www.example.com\r\n"
6088 "Connection: keep-alive\r\n\r\n");
6089 const MockWrite kGetAuth(
6090 "GET / HTTP/1.1\r\n"
6091 "Host: www.example.com\r\n"
6092 "Connection: keep-alive\r\n"
6093 "Authorization: auth_token\r\n\r\n");
6094
6095 const MockRead kServerChallenge(
6096 "HTTP/1.1 401 Unauthorized\r\n"
6097 "WWW-Authenticate: Mock realm=server\r\n"
6098 "Content-Type: text/html; charset=iso-8859-1\r\n"
6099 "Content-Length: 14\r\n\r\n"
6100 "Unauthorized\r\n");
6101 const MockRead kSuccess(
6102 "HTTP/1.1 200 OK\r\n"
6103 "Content-Type: text/html; charset=iso-8859-1\r\n"
6104 "Content-Length: 3\r\n\r\n"
6105 "Yes");
6106
6107 MockWrite writes[] = {
6108 // First round
6109 kGet,
6110 // Second round
6111 kGetAuth,
6112 // Third round
6113 kGetAuth,
6114 };
6115 MockRead reads[] = {
6116 // First round
6117 kServerChallenge,
6118 // Second round
6119 kServerChallenge,
6120 // Third round
6121 kSuccess,
6122 };
6123 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6124 writes, arraysize(writes));
6125 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6126
6127 // First round
6128 auth_handler->SetGenerateExpectation(false, OK);
6129 rv = trans->Start(&request, &callback, BoundNetLog());
6130 if (rv == ERR_IO_PENDING)
6131 rv = callback.WaitForResult();
6132 EXPECT_EQ(OK, rv);
6133 response = trans->GetResponseInfo();
6134 ASSERT_FALSE(response == NULL);
6135 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6136
6137 // Second round
6138 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446139 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146140 if (rv == ERR_IO_PENDING)
6141 rv = callback.WaitForResult();
6142 EXPECT_EQ(OK, rv);
6143 response = trans->GetResponseInfo();
6144 ASSERT_FALSE(response == NULL);
6145 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6146
6147 // Third round
6148 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446149 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146150 if (rv == ERR_IO_PENDING)
6151 rv = callback.WaitForResult();
6152 EXPECT_EQ(OK, rv);
6153 response = trans->GetResponseInfo();
6154 ASSERT_FALSE(response == NULL);
6155 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6156}
6157
[email protected]aeaca1f2010-04-20 22:05:216158class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6159 public:
[email protected]06650c52010-06-03 00:49:176160 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216161 : fail_all_(fail_all) {
6162 }
6163
6164 virtual MockRead GetNextRead() {
6165 if (fail_all_)
6166 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6167
6168 return MockRead(false /* async */,
6169 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6170 }
6171
6172 virtual MockWriteResult OnWrite(const std::string& data) {
6173 return MockWriteResult(false /* async */, data.size());
6174 }
6175
6176 void Reset() {
6177 }
6178
6179 private:
6180 const bool fail_all_;
6181};
6182
6183// Test that we restart a connection when we see a decompression failure from
6184// the peer during the handshake. (In the real world we'll restart with SSLv3
6185// and we won't offer DEFLATE in that case.)
6186TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6187 HttpRequestInfo request;
6188 request.method = "GET";
6189 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6190 request.load_flags = 0;
6191
6192 SessionDependencies session_deps;
6193 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6194 false /* fail all reads */);
6195 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6196 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116197 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216198 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6199 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6200 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6201 session_deps.socket_factory.AddSSLSocketDataProvider(
6202 &ssl_socket_data_provider1);
6203 session_deps.socket_factory.AddSSLSocketDataProvider(
6204 &ssl_socket_data_provider2);
6205
[email protected]e60e47a2010-07-14 03:37:186206 // Work around http://crbug.com/37454
6207 StaticSocketDataProvider bug37454_connection;
6208 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6209 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6210
[email protected]aeaca1f2010-04-20 22:05:216211 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6212 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6213 TestCompletionCallback callback;
6214
[email protected]5a1d7ca2010-04-28 20:12:276215 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216216 EXPECT_EQ(ERR_IO_PENDING, rv);
6217 EXPECT_EQ(OK, callback.WaitForResult());
6218
6219 const HttpResponseInfo* response = trans->GetResponseInfo();
6220 ASSERT_TRUE(response != NULL);
6221 ASSERT_TRUE(response->headers != NULL);
6222 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6223
6224 std::string response_data;
6225 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6226 EXPECT_EQ("ok.", response_data);
6227}
6228
6229// Test that we restart a connection if we get a decompression failure from the
6230// peer while reading the first bytes from the connection. This occurs when the
6231// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6232// in the handshake.
6233TEST_F(HttpNetworkTransactionTest,
6234 RestartAfterTLSDecompressionFailureWithFalseStart) {
6235 HttpRequestInfo request;
6236 request.method = "GET";
6237 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6238 request.load_flags = 0;
6239
6240 SessionDependencies session_deps;
6241 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6242 true /* fail all reads */);
6243 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6244 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6245 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6246 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6247 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6248 session_deps.socket_factory.AddSSLSocketDataProvider(
6249 &ssl_socket_data_provider1);
6250 session_deps.socket_factory.AddSSLSocketDataProvider(
6251 &ssl_socket_data_provider2);
6252
6253 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6254 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6255 TestCompletionCallback callback;
6256
[email protected]5a1d7ca2010-04-28 20:12:276257 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216258 EXPECT_EQ(ERR_IO_PENDING, rv);
6259 EXPECT_EQ(OK, callback.WaitForResult());
6260
6261 const HttpResponseInfo* response = trans->GetResponseInfo();
6262 ASSERT_TRUE(response != NULL);
6263 ASSERT_TRUE(response->headers != NULL);
6264 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6265
6266 std::string response_data;
6267 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6268 EXPECT_EQ("ok.", response_data);
6269}
6270
[email protected]65041fa2010-05-21 06:56:536271// This tests the case that a request is issued via http instead of spdy after
6272// npn is negotiated.
6273TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6274 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6275 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6276 SessionDependencies session_deps;
6277 HttpRequestInfo request;
6278 request.method = "GET";
6279 request.url = GURL("https://www.google.com/");
6280 request.load_flags = 0;
6281
6282 MockWrite data_writes[] = {
6283 MockWrite("GET / HTTP/1.1\r\n"
6284 "Host: www.google.com\r\n"
6285 "Connection: keep-alive\r\n\r\n"),
6286 };
6287
6288 MockRead data_reads[] = {
6289 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356290 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536291 MockRead("hello world"),
6292 MockRead(false, OK),
6293 };
6294
6295 SSLSocketDataProvider ssl(true, OK);
6296 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6297 ssl.next_proto = "http/1.1";
6298
6299 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6300
6301 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6302 data_writes, arraysize(data_writes));
6303 session_deps.socket_factory.AddSocketDataProvider(&data);
6304
6305 TestCompletionCallback callback;
6306
6307 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6308 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6309
6310 int rv = trans->Start(&request, &callback, BoundNetLog());
6311
6312 EXPECT_EQ(ERR_IO_PENDING, rv);
6313 EXPECT_EQ(OK, callback.WaitForResult());
6314
6315 const HttpResponseInfo* response = trans->GetResponseInfo();
6316 ASSERT_TRUE(response != NULL);
6317 ASSERT_TRUE(response->headers != NULL);
6318 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6319
6320 std::string response_data;
6321 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6322 EXPECT_EQ("hello world", response_data);
6323
6324 EXPECT_FALSE(response->was_fetched_via_spdy);
6325 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576326 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536327
6328 HttpNetworkTransaction::SetNextProtos("");
6329 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6330}
[email protected]26ef6582010-06-24 02:30:476331
6332TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6333 // Simulate the SSL handshake completing with an NPN negotiation
6334 // followed by an immediate server closing of the socket.
6335 // Fix crash: http://crbug.com/46369
6336 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:356337 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476338 SessionDependencies session_deps;
6339
6340 HttpRequestInfo request;
6341 request.method = "GET";
6342 request.url = GURL("https://www.google.com/");
6343 request.load_flags = 0;
6344
6345 SSLSocketDataProvider ssl(true, OK);
6346 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356347 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476348 ssl.was_npn_negotiated = true;
6349 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6350
[email protected]2bd93022010-07-17 00:58:446351 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136352 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476353
6354 MockRead spdy_reads[] = {
6355 MockRead(false, 0, 0) // Not async - return 0 immediately.
6356 };
6357
6358 scoped_refptr<DelayedSocketData> spdy_data(
6359 new DelayedSocketData(
6360 0, // don't wait in this case, immediate hangup.
6361 spdy_reads, arraysize(spdy_reads),
6362 spdy_writes, arraysize(spdy_writes)));
6363 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6364
6365 TestCompletionCallback callback;
6366
6367 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6368 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6369
6370 int rv = trans->Start(&request, &callback, BoundNetLog());
6371 EXPECT_EQ(ERR_IO_PENDING, rv);
6372 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6373
6374 HttpNetworkTransaction::SetNextProtos("");
6375 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6376}
[email protected]65d34382010-07-01 18:12:266377
[email protected]f45c1ee2010-08-03 00:54:306378TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
6379 // This test ensures that the URL passed into the proxy is upgraded
6380 // to https when doing an Alternate Protocol upgrade.
6381 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6382 HttpNetworkTransaction::SetNextProtos(
6383 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
6384
6385 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6386 HttpAuthHandlerMock::Factory* auth_factory =
6387 new HttpAuthHandlerMock::Factory();
6388 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
6389 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6390 auth_factory->set_do_init_from_challenge(true);
6391 session_deps.http_auth_handler_factory.reset(auth_factory);
6392
6393 HttpRequestInfo request;
6394 request.method = "GET";
6395 request.url = GURL("http://www.google.com");
6396 request.load_flags = 0;
6397
6398 // First round goes unauthenticated through the proxy.
6399 MockWrite data_writes_1[] = {
6400 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6401 "Host: www.google.com\r\n"
6402 "Proxy-Connection: keep-alive\r\n"
6403 "\r\n"),
6404 };
6405 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:596406 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:306407 MockRead("HTTP/1.1 200 OK\r\n"
6408 "Alternate-Protocol: 443:npn-spdy/2\r\n"
6409 "Proxy-Connection: close\r\n"
6410 "\r\n"),
6411 };
6412 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
6413 data_writes_1, arraysize(data_writes_1));
6414
6415 // Second round tries to tunnel to www.google.com due to the
6416 // Alternate-Protocol announcement in the first round. It fails due
6417 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:596418 // After the failure, a tunnel is established to www.google.com using
6419 // Proxy-Authorization headers. There is then a SPDY request round.
6420 //
6421 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
6422 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
6423 // does a Disconnect and Connect on the same socket, rather than trying
6424 // to obtain a new one.
6425 //
6426 // NOTE: Originally, the proxy response to the second CONNECT request
6427 // simply returned another 407 so the unit test could skip the SSL connection
6428 // establishment and SPDY framing issues. Alas, the
6429 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:306430 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:596431
[email protected]f45c1ee2010-08-03 00:54:306432 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6433 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6434 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6435
[email protected]394816e92010-08-03 07:38:596436 MockWrite data_writes_2[] = {
6437 // First connection attempt without Proxy-Authorization.
6438 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6439 "Host: www.google.com\r\n"
6440 "Proxy-Connection: keep-alive\r\n"
6441 "\r\n"),
6442
6443 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:306444 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6445 "Host: www.google.com\r\n"
6446 "Proxy-Connection: keep-alive\r\n"
6447 "Proxy-Authorization: auth_token\r\n"
6448 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:306449
[email protected]394816e92010-08-03 07:38:596450 // SPDY request
6451 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:306452 };
[email protected]394816e92010-08-03 07:38:596453 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
6454 "Proxy-Authenticate: Mock\r\n"
6455 "Proxy-Connection: close\r\n"
6456 "\r\n");
6457 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6458 MockRead data_reads_2[] = {
6459 // First connection attempt fails
6460 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
6461 MockRead(true, kRejectConnectResponse,
6462 arraysize(kRejectConnectResponse) - 1, 1),
6463
6464 // Second connection attempt passes
6465 MockRead(true, kAcceptConnectResponse,
6466 arraysize(kAcceptConnectResponse) -1, 4),
6467
6468 // SPDY response
6469 CreateMockRead(*resp.get(), 6),
6470 CreateMockRead(*data.get(), 6),
6471 MockRead(true, 0, 0, 6),
6472 };
6473 scoped_refptr<OrderedSocketData> data_2(
6474 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
6475 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:306476
6477 SSLSocketDataProvider ssl(true, OK);
6478 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6479 ssl.next_proto = "spdy/2";
6480 ssl.was_npn_negotiated = true;
6481
6482 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:596483 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:306484 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6485 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6486
6487 // First round should work and provide the Alternate-Protocol state.
6488 TestCompletionCallback callback_1;
6489 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
6490 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
6491 EXPECT_EQ(ERR_IO_PENDING, rv);
6492 EXPECT_EQ(OK, callback_1.WaitForResult());
6493
6494 // Second round should attempt a tunnel connect and get an auth challenge.
6495 TestCompletionCallback callback_2;
6496 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
6497 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
6498 EXPECT_EQ(ERR_IO_PENDING, rv);
6499 EXPECT_EQ(OK, callback_2.WaitForResult());
6500 const HttpResponseInfo* response = trans_2->GetResponseInfo();
6501 ASSERT_FALSE(response == NULL);
6502 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6503
6504 // Restart with auth. Tunnel should work and response received.
6505 TestCompletionCallback callback_3;
6506 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
6507 EXPECT_EQ(ERR_IO_PENDING, rv);
6508 EXPECT_EQ(OK, callback_3.WaitForResult());
6509
6510 // After all that work, these two lines (or actually, just the scheme) are
6511 // what this test is all about. Make sure it happens correctly.
6512 const GURL& request_url = auth_handler->request_url();
6513 EXPECT_EQ("https", request_url.scheme());
6514 EXPECT_EQ("www.google.com", request_url.host());
6515
6516 HttpNetworkTransaction::SetNextProtos("");
6517 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6518}
6519
[email protected]89ceba9a2009-03-21 03:46:066520} // namespace net