blob: d3cb28aa6dcf045e8776d83d8ec680207afacd6f [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
[email protected]da81f132010-08-18 23:39:293578TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
3579 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
3580 scoped_ptr<HttpTransaction> trans(
3581 new HttpNetworkTransaction(CreateSession(&session_deps)));
3582
3583 HttpRequestInfo request;
3584 request.method = "GET";
3585 request.url = GURL("https://www.google.com/");
3586 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
3587 "Chromium Ultra Awesome X Edition");
3588
3589 MockWrite data_writes[] = {
3590 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
3591 "Host: www.google.com\r\n"
3592 "Proxy-Connection: keep-alive\r\n"
3593 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
3594 };
3595 MockRead data_reads[] = {
3596 // Return an error, so the transaction stops here (this test isn't
3597 // interested in the rest).
3598 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
3599 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3600 MockRead("Proxy-Connection: close\r\n\r\n"),
3601 };
3602
3603 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3604 data_writes, arraysize(data_writes));
3605 session_deps.socket_factory.AddSocketDataProvider(&data);
3606
3607 TestCompletionCallback callback;
3608
3609 int rv = trans->Start(&request, &callback, BoundNetLog());
3610 EXPECT_EQ(ERR_IO_PENDING, rv);
3611
3612 rv = callback.WaitForResult();
3613 EXPECT_EQ(OK, rv);
3614}
3615
[email protected]1c773ea12009-04-28 19:58:423616TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:593617 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403618 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433619 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423620
3621 HttpRequestInfo request;
3622 request.method = "GET";
3623 request.url = GURL("http://www.google.com/");
3624 request.load_flags = 0;
3625 request.referrer = GURL("http://the.previous.site.com/");
3626
3627 MockWrite data_writes[] = {
3628 MockWrite("GET / HTTP/1.1\r\n"
3629 "Host: www.google.com\r\n"
3630 "Connection: keep-alive\r\n"
3631 "Referer: http://the.previous.site.com/\r\n\r\n"),
3632 };
3633
3634 // Lastly, the server responds with the actual content.
3635 MockRead data_reads[] = {
3636 MockRead("HTTP/1.0 200 OK\r\n"),
3637 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3638 MockRead("Content-Length: 100\r\n\r\n"),
3639 MockRead(false, OK),
3640 };
3641
[email protected]31a2bfe2010-02-09 08:03:393642 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3643 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593644 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423645
3646 TestCompletionCallback callback;
3647
[email protected]5a1d7ca2010-04-28 20:12:273648 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423649 EXPECT_EQ(ERR_IO_PENDING, rv);
3650
3651 rv = callback.WaitForResult();
3652 EXPECT_EQ(OK, rv);
3653}
3654
3655TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593656 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403657 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433658 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423659
3660 HttpRequestInfo request;
3661 request.method = "POST";
3662 request.url = GURL("http://www.google.com/");
3663
3664 MockWrite data_writes[] = {
3665 MockWrite("POST / HTTP/1.1\r\n"
3666 "Host: www.google.com\r\n"
3667 "Connection: keep-alive\r\n"
3668 "Content-Length: 0\r\n\r\n"),
3669 };
3670
3671 // Lastly, the server responds with the actual content.
3672 MockRead data_reads[] = {
3673 MockRead("HTTP/1.0 200 OK\r\n"),
3674 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3675 MockRead("Content-Length: 100\r\n\r\n"),
3676 MockRead(false, OK),
3677 };
3678
[email protected]31a2bfe2010-02-09 08:03:393679 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3680 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593681 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423682
3683 TestCompletionCallback callback;
3684
[email protected]5a1d7ca2010-04-28 20:12:273685 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423686 EXPECT_EQ(ERR_IO_PENDING, rv);
3687
3688 rv = callback.WaitForResult();
3689 EXPECT_EQ(OK, rv);
3690}
3691
3692TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593693 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403694 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433695 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423696
3697 HttpRequestInfo request;
3698 request.method = "PUT";
3699 request.url = GURL("http://www.google.com/");
3700
3701 MockWrite data_writes[] = {
3702 MockWrite("PUT / HTTP/1.1\r\n"
3703 "Host: www.google.com\r\n"
3704 "Connection: keep-alive\r\n"
3705 "Content-Length: 0\r\n\r\n"),
3706 };
3707
3708 // Lastly, the server responds with the actual content.
3709 MockRead data_reads[] = {
3710 MockRead("HTTP/1.0 200 OK\r\n"),
3711 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3712 MockRead("Content-Length: 100\r\n\r\n"),
3713 MockRead(false, OK),
3714 };
3715
[email protected]31a2bfe2010-02-09 08:03:393716 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3717 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593718 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423719
3720 TestCompletionCallback callback;
3721
[email protected]5a1d7ca2010-04-28 20:12:273722 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423723 EXPECT_EQ(ERR_IO_PENDING, rv);
3724
3725 rv = callback.WaitForResult();
3726 EXPECT_EQ(OK, rv);
3727}
3728
3729TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:593730 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403731 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433732 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423733
3734 HttpRequestInfo request;
3735 request.method = "HEAD";
3736 request.url = GURL("http://www.google.com/");
3737
3738 MockWrite data_writes[] = {
3739 MockWrite("HEAD / HTTP/1.1\r\n"
3740 "Host: www.google.com\r\n"
3741 "Connection: keep-alive\r\n"
3742 "Content-Length: 0\r\n\r\n"),
3743 };
3744
3745 // Lastly, the server responds with the actual content.
3746 MockRead data_reads[] = {
3747 MockRead("HTTP/1.0 200 OK\r\n"),
3748 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3749 MockRead("Content-Length: 100\r\n\r\n"),
3750 MockRead(false, OK),
3751 };
3752
[email protected]31a2bfe2010-02-09 08:03:393753 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3754 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593755 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423756
3757 TestCompletionCallback callback;
3758
[email protected]5a1d7ca2010-04-28 20:12:273759 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423760 EXPECT_EQ(ERR_IO_PENDING, rv);
3761
3762 rv = callback.WaitForResult();
3763 EXPECT_EQ(OK, rv);
3764}
3765
3766TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:593767 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403768 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433769 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423770
3771 HttpRequestInfo request;
3772 request.method = "GET";
3773 request.url = GURL("http://www.google.com/");
3774 request.load_flags = LOAD_BYPASS_CACHE;
3775
3776 MockWrite data_writes[] = {
3777 MockWrite("GET / HTTP/1.1\r\n"
3778 "Host: www.google.com\r\n"
3779 "Connection: keep-alive\r\n"
3780 "Pragma: no-cache\r\n"
3781 "Cache-Control: no-cache\r\n\r\n"),
3782 };
3783
3784 // Lastly, the server responds with the actual content.
3785 MockRead data_reads[] = {
3786 MockRead("HTTP/1.0 200 OK\r\n"),
3787 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3788 MockRead("Content-Length: 100\r\n\r\n"),
3789 MockRead(false, OK),
3790 };
3791
[email protected]31a2bfe2010-02-09 08:03:393792 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3793 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593794 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423795
3796 TestCompletionCallback callback;
3797
[email protected]5a1d7ca2010-04-28 20:12:273798 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423799 EXPECT_EQ(ERR_IO_PENDING, rv);
3800
3801 rv = callback.WaitForResult();
3802 EXPECT_EQ(OK, rv);
3803}
3804
3805TEST_F(HttpNetworkTransactionTest,
3806 BuildRequest_CacheControlValidateCache) {
[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/");
3814 request.load_flags = LOAD_VALIDATE_CACHE;
3815
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 "Cache-Control: max-age=0\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
3844TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:593845 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403846 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433847 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:423848
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("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:423853
3854 MockWrite data_writes[] = {
3855 MockWrite("GET / HTTP/1.1\r\n"
3856 "Host: www.google.com\r\n"
3857 "Connection: keep-alive\r\n"
3858 "FooHeader: Bar\r\n\r\n"),
3859 };
3860
3861 // Lastly, the server responds with the actual content.
3862 MockRead data_reads[] = {
3863 MockRead("HTTP/1.0 200 OK\r\n"),
3864 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3865 MockRead("Content-Length: 100\r\n\r\n"),
3866 MockRead(false, OK),
3867 };
3868
[email protected]31a2bfe2010-02-09 08:03:393869 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3870 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593871 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:423872
3873 TestCompletionCallback callback;
3874
[email protected]5a1d7ca2010-04-28 20:12:273875 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423876 EXPECT_EQ(ERR_IO_PENDING, rv);
3877
3878 rv = callback.WaitForResult();
3879 EXPECT_EQ(OK, rv);
3880}
3881
[email protected]270c6412010-03-29 22:02:473882TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
3883 SessionDependencies session_deps;
3884 scoped_ptr<HttpTransaction> trans(
3885 new HttpNetworkTransaction(CreateSession(&session_deps)));
3886
3887 HttpRequestInfo request;
3888 request.method = "GET";
3889 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:433890 request.extra_headers.SetHeader("referer", "www.foo.com");
3891 request.extra_headers.SetHeader("hEllo", "Kitty");
3892 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:473893
3894 MockWrite data_writes[] = {
3895 MockWrite("GET / HTTP/1.1\r\n"
3896 "Host: www.google.com\r\n"
3897 "Connection: keep-alive\r\n"
3898 "hEllo: Kitty\r\n"
3899 "FoO: bar\r\n\r\n"),
3900 };
3901
3902 // Lastly, the server responds with the actual content.
3903 MockRead data_reads[] = {
3904 MockRead("HTTP/1.0 200 OK\r\n"),
3905 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3906 MockRead("Content-Length: 100\r\n\r\n"),
3907 MockRead(false, OK),
3908 };
3909
3910 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3911 data_writes, arraysize(data_writes));
3912 session_deps.socket_factory.AddSocketDataProvider(&data);
3913
3914 TestCompletionCallback callback;
3915
[email protected]5a1d7ca2010-04-28 20:12:273916 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:473917 EXPECT_EQ(ERR_IO_PENDING, rv);
3918
3919 rv = callback.WaitForResult();
3920 EXPECT_EQ(OK, rv);
3921}
3922
[email protected]3cd17242009-06-23 02:59:023923TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:093924 SessionDependencies session_deps(
3925 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023926
3927 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433928 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023929
3930 HttpRequestInfo request;
3931 request.method = "GET";
3932 request.url = GURL("http://www.google.com/");
3933 request.load_flags = 0;
3934
3935 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
3936 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3937
3938 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353939 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023940 MockWrite("GET / HTTP/1.1\r\n"
3941 "Host: www.google.com\r\n"
3942 "Connection: keep-alive\r\n\r\n")
3943 };
3944
3945 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:593946 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:023947 MockRead("HTTP/1.0 200 OK\r\n"),
3948 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
3949 MockRead("Payload"),
3950 MockRead(false, OK)
3951 };
3952
[email protected]31a2bfe2010-02-09 08:03:393953 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3954 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593955 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:023956
3957 TestCompletionCallback callback;
3958
[email protected]5a1d7ca2010-04-28 20:12:273959 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:023960 EXPECT_EQ(ERR_IO_PENDING, rv);
3961
3962 rv = callback.WaitForResult();
3963 EXPECT_EQ(OK, rv);
3964
3965 const HttpResponseInfo* response = trans->GetResponseInfo();
3966 EXPECT_FALSE(response == NULL);
3967
3968 std::string response_text;
3969 rv = ReadTransaction(trans.get(), &response_text);
3970 EXPECT_EQ(OK, rv);
3971 EXPECT_EQ("Payload", response_text);
3972}
3973
3974TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:093975 SessionDependencies session_deps(
3976 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:023977
3978 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433979 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:023980
3981 HttpRequestInfo request;
3982 request.method = "GET";
3983 request.url = GURL("https://www.google.com/");
3984 request.load_flags = 0;
3985
3986 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
3987 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
3988
3989 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:353990 MockWrite(true, reinterpret_cast<char*>(write_buffer),
3991 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:023992 MockWrite("GET / HTTP/1.1\r\n"
3993 "Host: www.google.com\r\n"
3994 "Connection: keep-alive\r\n\r\n")
3995 };
3996
3997 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:353998 MockWrite(true, reinterpret_cast<char*>(read_buffer),
3999 arraysize(read_buffer)),
4000 MockRead("HTTP/1.0 200 OK\r\n"),
4001 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4002 MockRead("Payload"),
4003 MockRead(false, OK)
4004 };
4005
[email protected]31a2bfe2010-02-09 08:03:394006 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4007 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594008 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354009
[email protected]5ecc992a42009-11-11 01:41:594010 SSLSocketDataProvider ssl(true, OK);
4011 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354012
4013 TestCompletionCallback callback;
4014
[email protected]5a1d7ca2010-04-28 20:12:274015 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354016 EXPECT_EQ(ERR_IO_PENDING, rv);
4017
4018 rv = callback.WaitForResult();
4019 EXPECT_EQ(OK, rv);
4020
4021 const HttpResponseInfo* response = trans->GetResponseInfo();
4022 EXPECT_FALSE(response == NULL);
4023
4024 std::string response_text;
4025 rv = ReadTransaction(trans.get(), &response_text);
4026 EXPECT_EQ(OK, rv);
4027 EXPECT_EQ("Payload", response_text);
4028}
4029
4030TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094031 SessionDependencies session_deps(
4032 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354033
4034 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434035 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354036
4037 HttpRequestInfo request;
4038 request.method = "GET";
4039 request.url = GURL("http://www.google.com/");
4040 request.load_flags = 0;
4041
4042 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4043 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374044 const char kSOCKS5OkRequest[] = {
4045 0x05, // Version
4046 0x01, // Command (CONNECT)
4047 0x00, // Reserved.
4048 0x03, // Address type (DOMAINNAME).
4049 0x0E, // Length of domain (14)
4050 // Domain string:
4051 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4052 0x00, 0x50, // 16-bit port (80)
4053 };
[email protected]e0c27be2009-07-15 13:09:354054 const char kSOCKS5OkResponse[] =
4055 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4056
4057 MockWrite data_writes[] = {
4058 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4059 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4060 MockWrite("GET / HTTP/1.1\r\n"
4061 "Host: www.google.com\r\n"
4062 "Connection: keep-alive\r\n\r\n")
4063 };
4064
4065 MockRead data_reads[] = {
4066 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4067 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4068 MockRead("HTTP/1.0 200 OK\r\n"),
4069 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4070 MockRead("Payload"),
4071 MockRead(false, OK)
4072 };
4073
[email protected]31a2bfe2010-02-09 08:03:394074 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4075 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594076 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354077
4078 TestCompletionCallback callback;
4079
[email protected]5a1d7ca2010-04-28 20:12:274080 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354081 EXPECT_EQ(ERR_IO_PENDING, rv);
4082
4083 rv = callback.WaitForResult();
4084 EXPECT_EQ(OK, rv);
4085
4086 const HttpResponseInfo* response = trans->GetResponseInfo();
4087 EXPECT_FALSE(response == NULL);
4088
4089 std::string response_text;
4090 rv = ReadTransaction(trans.get(), &response_text);
4091 EXPECT_EQ(OK, rv);
4092 EXPECT_EQ("Payload", response_text);
4093}
4094
4095TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094096 SessionDependencies session_deps(
4097 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354098
4099 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434100 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354101
4102 HttpRequestInfo request;
4103 request.method = "GET";
4104 request.url = GURL("https://www.google.com/");
4105 request.load_flags = 0;
4106
4107 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4108 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374109 const unsigned char kSOCKS5OkRequest[] = {
4110 0x05, // Version
4111 0x01, // Command (CONNECT)
4112 0x00, // Reserved.
4113 0x03, // Address type (DOMAINNAME).
4114 0x0E, // Length of domain (14)
4115 // Domain string:
4116 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4117 0x01, 0xBB, // 16-bit port (443)
4118 };
4119
[email protected]e0c27be2009-07-15 13:09:354120 const char kSOCKS5OkResponse[] =
4121 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4122
4123 MockWrite data_writes[] = {
4124 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4125 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4126 arraysize(kSOCKS5OkRequest)),
4127 MockWrite("GET / HTTP/1.1\r\n"
4128 "Host: www.google.com\r\n"
4129 "Connection: keep-alive\r\n\r\n")
4130 };
4131
4132 MockRead data_reads[] = {
4133 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4134 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024135 MockRead("HTTP/1.0 200 OK\r\n"),
4136 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4137 MockRead("Payload"),
4138 MockRead(false, OK)
4139 };
4140
[email protected]31a2bfe2010-02-09 08:03:394141 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4142 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594143 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024144
[email protected]5ecc992a42009-11-11 01:41:594145 SSLSocketDataProvider ssl(true, OK);
4146 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024147
4148 TestCompletionCallback callback;
4149
[email protected]5a1d7ca2010-04-28 20:12:274150 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024151 EXPECT_EQ(ERR_IO_PENDING, rv);
4152
4153 rv = callback.WaitForResult();
4154 EXPECT_EQ(OK, rv);
4155
4156 const HttpResponseInfo* response = trans->GetResponseInfo();
4157 EXPECT_FALSE(response == NULL);
4158
4159 std::string response_text;
4160 rv = ReadTransaction(trans.get(), &response_text);
4161 EXPECT_EQ(OK, rv);
4162 EXPECT_EQ("Payload", response_text);
4163}
4164
[email protected]04e5be32009-06-26 20:00:314165// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064166
4167struct GroupNameTest {
4168 std::string proxy_server;
4169 std::string url;
4170 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184171 bool ssl;
[email protected]2d731a32010-04-29 01:04:064172};
4173
4174scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4175 const std::string& proxy_server) {
4176 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4177 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4178
4179 HttpAlternateProtocols* alternate_protocols =
4180 session->mutable_alternate_protocols();
4181 alternate_protocols->SetAlternateProtocolFor(
4182 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354183 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064184
4185 return session;
4186}
4187
4188int GroupNameTransactionHelper(
4189 const std::string& url,
4190 const scoped_refptr<HttpNetworkSession>& session) {
4191 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4192
4193 HttpRequestInfo request;
4194 request.method = "GET";
4195 request.url = GURL(url);
4196 request.load_flags = 0;
4197
4198 TestCompletionCallback callback;
4199
4200 // We do not complete this request, the dtor will clean the transaction up.
4201 return trans->Start(&request, &callback, BoundNetLog());
4202}
4203
4204TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4205 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314206 {
[email protected]2d731a32010-04-29 01:04:064207 "", // unused
[email protected]04e5be32009-06-26 20:00:314208 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544209 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184210 false,
[email protected]2ff8b312010-04-26 22:20:544211 },
4212 {
[email protected]2d731a32010-04-29 01:04:064213 "", // unused
[email protected]2ff8b312010-04-26 22:20:544214 "http://[2001:1418:13:1::25]/direct",
4215 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184216 false,
[email protected]04e5be32009-06-26 20:00:314217 },
[email protected]04e5be32009-06-26 20:00:314218
4219 // SSL Tests
4220 {
[email protected]2d731a32010-04-29 01:04:064221 "", // unused
[email protected]04e5be32009-06-26 20:00:314222 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024223 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184224 true,
[email protected]04e5be32009-06-26 20:00:314225 },
4226 {
[email protected]2d731a32010-04-29 01:04:064227 "", // unused
4228 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024229 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184230 true,
[email protected]04e5be32009-06-26 20:00:314231 },
4232 {
[email protected]2d731a32010-04-29 01:04:064233 "", // unused
[email protected]2ff8b312010-04-26 22:20:544234 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024235 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184236 true,
[email protected]2ff8b312010-04-26 22:20:544237 },
[email protected]2d731a32010-04-29 01:04:064238 };
[email protected]2ff8b312010-04-26 22:20:544239
[email protected]2d731a32010-04-29 01:04:064240 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4241
4242 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4243 scoped_refptr<HttpNetworkSession> session(
4244 SetupSessionForGroupNameTests(tests[i].proxy_server));
4245
4246 HttpNetworkSessionPeer peer(session);
4247 scoped_refptr<CaptureGroupNameTCPSocketPool> tcp_conn_pool(
4248 new CaptureGroupNameTCPSocketPool(session.get()));
4249 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]e60e47a2010-07-14 03:37:184250 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4251 new CaptureGroupNameSSLSocketPool(session.get()));
4252 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064253
4254 EXPECT_EQ(ERR_IO_PENDING,
4255 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184256 if (tests[i].ssl)
4257 EXPECT_EQ(tests[i].expected_group_name,
4258 ssl_conn_pool->last_group_name_received());
4259 else
4260 EXPECT_EQ(tests[i].expected_group_name,
4261 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064262 }
4263
4264 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4265}
4266
4267TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4268 const GroupNameTest tests[] = {
4269 {
4270 "http_proxy",
4271 "http://www.google.com/http_proxy_normal",
4272 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184273 false,
[email protected]2d731a32010-04-29 01:04:064274 },
4275
4276 // SSL Tests
4277 {
4278 "http_proxy",
4279 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024280 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184281 true,
[email protected]2d731a32010-04-29 01:04:064282 },
4283
[email protected]9faeded92010-04-29 20:03:054284 {
4285 "http_proxy",
4286 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024287 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184288 true,
[email protected]9faeded92010-04-29 20:03:054289 },
[email protected]2d731a32010-04-29 01:04:064290 };
4291
4292 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4293
4294 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4295 scoped_refptr<HttpNetworkSession> session(
4296 SetupSessionForGroupNameTests(tests[i].proxy_server));
4297
4298 HttpNetworkSessionPeer peer(session);
4299
[email protected]e60e47a2010-07-14 03:37:184300 HostPortPair proxy_host("http_proxy", 80);
[email protected]e772db3f2010-07-12 18:11:134301 scoped_refptr<CaptureGroupNameHttpProxySocketPool> http_proxy_pool(
4302 new CaptureGroupNameHttpProxySocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184303 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
4304 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4305 new CaptureGroupNameSSLSocketPool(session.get()));
4306 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064307
4308 EXPECT_EQ(ERR_IO_PENDING,
4309 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184310 if (tests[i].ssl)
4311 EXPECT_EQ(tests[i].expected_group_name,
4312 ssl_conn_pool->last_group_name_received());
4313 else
4314 EXPECT_EQ(tests[i].expected_group_name,
4315 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064316 }
4317
4318 HttpNetworkTransaction::SetUseAlternateProtocols(false);
4319}
4320
4321TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4322 const GroupNameTest tests[] = {
4323 {
4324 "socks4://socks_proxy:1080",
4325 "http://www.google.com/socks4_direct",
4326 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184327 false,
[email protected]2d731a32010-04-29 01:04:064328 },
4329 {
4330 "socks5://socks_proxy:1080",
4331 "http://www.google.com/socks5_direct",
4332 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184333 false,
[email protected]2d731a32010-04-29 01:04:064334 },
4335
4336 // SSL Tests
4337 {
4338 "socks4://socks_proxy:1080",
4339 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024340 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184341 true,
[email protected]2d731a32010-04-29 01:04:064342 },
4343 {
4344 "socks5://socks_proxy:1080",
4345 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024346 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184347 true,
[email protected]2d731a32010-04-29 01:04:064348 },
4349
[email protected]9faeded92010-04-29 20:03:054350 {
4351 "socks4://socks_proxy:1080",
4352 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024353 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184354 true,
[email protected]9faeded92010-04-29 20:03:054355 },
[email protected]04e5be32009-06-26 20:00:314356 };
4357
[email protected]2ff8b312010-04-26 22:20:544358 HttpNetworkTransaction::SetUseAlternateProtocols(true);
4359
[email protected]04e5be32009-06-26 20:00:314360 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064361 scoped_refptr<HttpNetworkSession> session(
4362 SetupSessionForGroupNameTests(tests[i].proxy_server));
4363 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314364
[email protected]e60e47a2010-07-14 03:37:184365 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]a796bcec2010-03-22 17:17:264366 scoped_refptr<CaptureGroupNameSOCKSSocketPool> socks_conn_pool(
[email protected]2d731a32010-04-29 01:04:064367 new CaptureGroupNameSOCKSSocketPool(session.get()));
[email protected]e60e47a2010-07-14 03:37:184368 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
4369 scoped_refptr<CaptureGroupNameSSLSocketPool> ssl_conn_pool(
4370 new CaptureGroupNameSSLSocketPool(session.get()));
4371 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314372
[email protected]5695b8c2009-09-30 21:36:434373 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314374
[email protected]2d731a32010-04-29 01:04:064375 EXPECT_EQ(ERR_IO_PENDING,
4376 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184377 if (tests[i].ssl)
4378 EXPECT_EQ(tests[i].expected_group_name,
4379 ssl_conn_pool->last_group_name_received());
4380 else
4381 EXPECT_EQ(tests[i].expected_group_name,
4382 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314383 }
[email protected]2ff8b312010-04-26 22:20:544384
4385 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]04e5be32009-06-26 20:00:314386}
4387
[email protected]9172a982009-06-06 00:30:254388TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:544389 SessionDependencies session_deps(
4390 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:324391
[email protected]69719062010-01-05 20:09:214392 // This simulates failure resolving all hostnames; that means we will fail
4393 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:324394 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
4395
[email protected]9172a982009-06-06 00:30:254396 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434397 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:254398
4399 HttpRequestInfo request;
4400 request.method = "GET";
4401 request.url = GURL("http://www.google.com/");
4402
4403 TestCompletionCallback callback;
4404
[email protected]5a1d7ca2010-04-28 20:12:274405 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:254406 EXPECT_EQ(ERR_IO_PENDING, rv);
4407
[email protected]9172a982009-06-06 00:30:254408 rv = callback.WaitForResult();
4409 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4410}
4411
[email protected]f3e6c1e2009-06-15 20:52:124412// Host resolution observer used by
4413// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
4414// resovle requests are issued with a referrer of |expected_referrer|.
4415class ResolutionReferrerObserver : public HostResolver::Observer {
4416 public:
4417 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
4418 : expected_referrer_(expected_referrer),
4419 called_start_with_referrer_(false),
4420 called_finish_with_referrer_(false) {
4421 }
4422
4423 virtual void OnStartResolution(int id,
4424 const HostResolver::RequestInfo& info) {
4425 if (info.referrer() == expected_referrer_)
4426 called_start_with_referrer_ = true;
4427 }
4428
4429 virtual void OnFinishResolutionWithStatus(
4430 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
4431 if (info.referrer() == expected_referrer_)
4432 called_finish_with_referrer_ = true;
4433 }
4434
[email protected]eb255d32009-06-17 02:11:034435 virtual void OnCancelResolution(int id,
4436 const HostResolver::RequestInfo& info ) {
4437 FAIL() << "Should not be cancelling any requests!";
4438 }
4439
[email protected]f3e6c1e2009-06-15 20:52:124440 bool did_complete_with_expected_referrer() const {
4441 return called_start_with_referrer_ && called_finish_with_referrer_;
4442 }
4443
4444 private:
4445 GURL expected_referrer_;
4446 bool called_start_with_referrer_;
4447 bool called_finish_with_referrer_;
4448
4449 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
4450};
4451
4452// Make sure that when HostResolver::Resolve() is invoked, it passes through
4453// the "referrer". This is depended on by the DNS prefetch observer.
4454TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
4455 GURL referrer = GURL("http://expected-referrer/");
4456 EXPECT_TRUE(referrer.is_valid());
4457 ResolutionReferrerObserver resolution_observer(referrer);
4458
4459 SessionDependencies session_deps;
4460 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434461 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:124462
4463 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:144464 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:124465
4466 // Connect up a mock socket which will fail when reading.
4467 MockRead data_reads[] = {
4468 MockRead(false, ERR_FAILED),
4469 };
[email protected]31a2bfe2010-02-09 08:03:394470 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594471 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:124472
4473 // Issue a request, containing an HTTP referrer.
4474 HttpRequestInfo request;
4475 request.method = "GET";
4476 request.referrer = referrer;
4477 request.url = GURL("http://www.google.com/");
4478
4479 // Run the request until it fails reading from the socket.
4480 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274481 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:124482 EXPECT_EQ(ERR_IO_PENDING, rv);
4483 rv = callback.WaitForResult();
4484 EXPECT_EQ(ERR_FAILED, rv);
4485
4486 // Check that the host resolution observer saw |referrer|.
4487 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
4488}
4489
[email protected]685af592010-05-11 19:31:244490// Base test to make sure that when the load flags for a request specify to
4491// bypass the cache, the DNS cache is not used.
4492void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:284493 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:324494
[email protected]a2c2fb92009-07-18 07:31:044495 // Select a host resolver that does caching.
4496 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:324497
[email protected]3b9cca42009-06-16 01:08:284498 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:434499 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:284500
4501 // Warm up the host cache so it has an entry for "www.google.com" (by doing
4502 // a synchronous lookup.)
4503 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:144504 int rv = session_deps.host_resolver->Resolve(
[email protected]684970b2009-08-14 04:54:464505 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274506 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284507 EXPECT_EQ(OK, rv);
4508
4509 // Verify that it was added to host cache, by doing a subsequent async lookup
4510 // and confirming it completes synchronously.
4511 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:464512 rv = session_deps.host_resolver->Resolve(
[email protected]3b9cca42009-06-16 01:08:284513 HostResolver::RequestInfo("www.google.com", 80), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:274514 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:324515 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:284516
4517 // Inject a failure the next time that "www.google.com" is resolved. This way
4518 // we can tell if the next lookup hit the cache, or the "network".
4519 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:324520 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:284521
4522 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
4523 // first read -- this won't be reached as the host resolution will fail first.
4524 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:394525 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594526 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:284527
4528 // Issue a request, asking to bypass the cache(s).
4529 HttpRequestInfo request;
4530 request.method = "GET";
[email protected]685af592010-05-11 19:31:244531 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:284532 request.url = GURL("http://www.google.com/");
4533
4534 // Run the request.
4535 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:274536 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:284537 ASSERT_EQ(ERR_IO_PENDING, rv);
4538 rv = callback.WaitForResult();
4539
4540 // If we bypassed the cache, we would have gotten a failure while resolving
4541 // "www.google.com".
4542 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
4543}
4544
[email protected]685af592010-05-11 19:31:244545// There are multiple load flags that should trigger the host cache bypass.
4546// Test each in isolation:
4547TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
4548 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
4549}
4550
4551TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
4552 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
4553}
4554
4555TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
4556 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
4557}
4558
[email protected]0877e3d2009-10-17 22:29:574559// Make sure we can handle an error when writing the request.
4560TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
4561 SessionDependencies session_deps;
4562 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4563
4564 HttpRequestInfo request;
4565 request.method = "GET";
4566 request.url = GURL("http://www.foo.com/");
4567 request.load_flags = 0;
4568
4569 MockWrite write_failure[] = {
4570 MockWrite(true, ERR_CONNECTION_RESET),
4571 };
[email protected]31a2bfe2010-02-09 08:03:394572 StaticSocketDataProvider data(NULL, 0,
4573 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:594574 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574575
4576 TestCompletionCallback callback;
4577
4578 scoped_ptr<HttpTransaction> trans(
4579 new HttpNetworkTransaction(CreateSession(&session_deps)));
4580
[email protected]5a1d7ca2010-04-28 20:12:274581 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574582 EXPECT_EQ(ERR_IO_PENDING, rv);
4583
4584 rv = callback.WaitForResult();
4585 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
4586}
4587
4588// Check that a connection closed after the start of the headers finishes ok.
4589TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
4590 SessionDependencies session_deps;
4591 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
4592
4593 HttpRequestInfo request;
4594 request.method = "GET";
4595 request.url = GURL("http://www.foo.com/");
4596 request.load_flags = 0;
4597
4598 MockRead data_reads[] = {
4599 MockRead("HTTP/1."),
4600 MockRead(false, OK),
4601 };
4602
[email protected]31a2bfe2010-02-09 08:03:394603 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594604 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:574605
4606 TestCompletionCallback callback;
4607
4608 scoped_ptr<HttpTransaction> trans(
4609 new HttpNetworkTransaction(CreateSession(&session_deps)));
4610
[email protected]5a1d7ca2010-04-28 20:12:274611 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574612 EXPECT_EQ(ERR_IO_PENDING, rv);
4613
4614 rv = callback.WaitForResult();
4615 EXPECT_EQ(OK, rv);
4616
4617 const HttpResponseInfo* response = trans->GetResponseInfo();
4618 EXPECT_TRUE(response != NULL);
4619
4620 EXPECT_TRUE(response->headers != NULL);
4621 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4622
4623 std::string response_data;
4624 rv = ReadTransaction(trans.get(), &response_data);
4625 EXPECT_EQ(OK, rv);
4626 EXPECT_EQ("", response_data);
4627}
4628
4629// Make sure that a dropped connection while draining the body for auth
4630// restart does the right thing.
4631TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
4632 SessionDependencies session_deps;
4633 scoped_ptr<HttpTransaction> trans(
4634 new HttpNetworkTransaction(CreateSession(&session_deps)));
4635
4636 HttpRequestInfo request;
4637 request.method = "GET";
4638 request.url = GURL("http://www.google.com/");
4639 request.load_flags = 0;
4640
4641 MockWrite data_writes1[] = {
4642 MockWrite("GET / HTTP/1.1\r\n"
4643 "Host: www.google.com\r\n"
4644 "Connection: keep-alive\r\n\r\n"),
4645 };
4646
4647 MockRead data_reads1[] = {
4648 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4649 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4650 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4651 MockRead("Content-Length: 14\r\n\r\n"),
4652 MockRead("Unauth"),
4653 MockRead(true, ERR_CONNECTION_RESET),
4654 };
4655
[email protected]31a2bfe2010-02-09 08:03:394656 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4657 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594658 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:574659
4660 // After calling trans->RestartWithAuth(), this is the request we should
4661 // be issuing -- the final header line contains the credentials.
4662 MockWrite data_writes2[] = {
4663 MockWrite("GET / HTTP/1.1\r\n"
4664 "Host: www.google.com\r\n"
4665 "Connection: keep-alive\r\n"
4666 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4667 };
4668
4669 // Lastly, the server responds with the actual content.
4670 MockRead data_reads2[] = {
4671 MockRead("HTTP/1.1 200 OK\r\n"),
4672 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4673 MockRead("Content-Length: 100\r\n\r\n"),
4674 MockRead(false, OK),
4675 };
4676
[email protected]31a2bfe2010-02-09 08:03:394677 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4678 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594679 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:574680
4681 TestCompletionCallback callback1;
4682
[email protected]5a1d7ca2010-04-28 20:12:274683 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574684 EXPECT_EQ(ERR_IO_PENDING, rv);
4685
4686 rv = callback1.WaitForResult();
4687 EXPECT_EQ(OK, rv);
4688
4689 const HttpResponseInfo* response = trans->GetResponseInfo();
4690 EXPECT_FALSE(response == NULL);
4691
4692 // The password prompt info should have been set in response->auth_challenge.
4693 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4694
4695 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4696 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4697 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4698
4699 TestCompletionCallback callback2;
4700
[email protected]13c8a092010-07-29 06:15:444701 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:574702 EXPECT_EQ(ERR_IO_PENDING, rv);
4703
4704 rv = callback2.WaitForResult();
4705 EXPECT_EQ(OK, rv);
4706
4707 response = trans->GetResponseInfo();
4708 EXPECT_FALSE(response == NULL);
4709 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4710 EXPECT_EQ(100, response->headers->GetContentLength());
4711}
4712
4713// Test HTTPS connections going through a proxy that sends extra data.
4714TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
4715 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4716
4717 HttpRequestInfo request;
4718 request.method = "GET";
4719 request.url = GURL("https://www.google.com/");
4720 request.load_flags = 0;
4721
4722 MockRead proxy_reads[] = {
4723 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
4724 MockRead(false, OK)
4725 };
4726
[email protected]31a2bfe2010-02-09 08:03:394727 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:594728 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:574729
[email protected]5ecc992a42009-11-11 01:41:594730 session_deps.socket_factory.AddSocketDataProvider(&data);
4731 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:574732
4733 TestCompletionCallback callback;
4734
4735 session_deps.socket_factory.ResetNextMockIndexes();
4736
4737 scoped_ptr<HttpTransaction> trans(
4738 new HttpNetworkTransaction(CreateSession(&session_deps)));
4739
[email protected]5a1d7ca2010-04-28 20:12:274740 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:574741 EXPECT_EQ(ERR_IO_PENDING, rv);
4742
4743 rv = callback.WaitForResult();
4744 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
4745}
4746
[email protected]e22e1362009-11-23 21:31:124747TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:464748 SessionDependencies session_deps;
4749 scoped_ptr<HttpTransaction> trans(
4750 new HttpNetworkTransaction(CreateSession(&session_deps)));
4751
4752 HttpRequestInfo request;
4753 request.method = "GET";
4754 request.url = GURL("http://www.google.com/");
4755 request.load_flags = 0;
4756
[email protected]e22e1362009-11-23 21:31:124757 MockRead data_reads[] = {
4758 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
4759 MockRead(false, OK),
4760 };
[email protected]9492e4a2010-02-24 00:58:464761
4762 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
4763 session_deps.socket_factory.AddSocketDataProvider(&data);
4764
4765 TestCompletionCallback callback;
4766
[email protected]5a1d7ca2010-04-28 20:12:274767 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:464768 EXPECT_EQ(ERR_IO_PENDING, rv);
4769
4770 EXPECT_EQ(OK, callback.WaitForResult());
4771
4772 const HttpResponseInfo* response = trans->GetResponseInfo();
4773 EXPECT_TRUE(response != NULL);
4774
4775 EXPECT_TRUE(response->headers != NULL);
4776 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4777
4778 std::string response_data;
4779 rv = ReadTransaction(trans.get(), &response_data);
4780 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:124781}
4782
[email protected]95d88ffe2010-02-04 21:25:334783TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
4784 SessionDependencies session_deps;
4785 scoped_ptr<HttpTransaction> trans(
4786 new HttpNetworkTransaction(CreateSession(&session_deps)));
4787
4788 HttpRequestInfo request;
4789 request.method = "POST";
4790 request.url = GURL("http://www.google.com/upload");
4791 request.upload_data = new UploadData;
4792 request.load_flags = 0;
4793
4794 FilePath temp_file_path;
4795 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
4796 const uint64 kFakeSize = 100000; // file is actually blank
4797
4798 std::vector<UploadData::Element> elements;
4799 UploadData::Element element;
4800 element.SetToFilePath(temp_file_path);
4801 element.SetContentLength(kFakeSize);
4802 elements.push_back(element);
4803 request.upload_data->set_elements(elements);
4804 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
4805
4806 MockRead data_reads[] = {
4807 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4808 MockRead("hello world"),
4809 MockRead(false, OK),
4810 };
[email protected]31a2bfe2010-02-09 08:03:394811 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:334812 session_deps.socket_factory.AddSocketDataProvider(&data);
4813
4814 TestCompletionCallback callback;
4815
[email protected]5a1d7ca2010-04-28 20:12:274816 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:334817 EXPECT_EQ(ERR_IO_PENDING, rv);
4818
4819 rv = callback.WaitForResult();
4820 EXPECT_EQ(OK, rv);
4821
4822 const HttpResponseInfo* response = trans->GetResponseInfo();
4823 EXPECT_TRUE(response != NULL);
4824
4825 EXPECT_TRUE(response->headers != NULL);
4826 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4827
4828 std::string response_data;
4829 rv = ReadTransaction(trans.get(), &response_data);
4830 EXPECT_EQ(OK, rv);
4831 EXPECT_EQ("hello world", response_data);
4832
4833 file_util::Delete(temp_file_path, false);
4834}
4835
[email protected]6624b4622010-03-29 19:58:364836TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
4837 // If we try to upload an unreadable file, the network stack should report
4838 // the file size as zero and upload zero bytes for that file.
4839 SessionDependencies session_deps;
4840 scoped_ptr<HttpTransaction> trans(
4841 new HttpNetworkTransaction(CreateSession(&session_deps)));
4842
4843 FilePath temp_file;
4844 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4845 std::string temp_file_content("Unreadable file.");
4846 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
4847 temp_file_content.length()));
4848 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4849
4850 HttpRequestInfo request;
4851 request.method = "POST";
4852 request.url = GURL("http://www.google.com/upload");
4853 request.upload_data = new UploadData;
4854 request.load_flags = 0;
4855
4856 std::vector<UploadData::Element> elements;
4857 UploadData::Element element;
4858 element.SetToFilePath(temp_file);
4859 elements.push_back(element);
4860 request.upload_data->set_elements(elements);
4861
4862 MockRead data_reads[] = {
4863 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
4864 MockRead(false, OK),
4865 };
4866 MockWrite data_writes[] = {
4867 MockWrite("POST /upload HTTP/1.1\r\n"
4868 "Host: www.google.com\r\n"
4869 "Connection: keep-alive\r\n"
4870 "Content-Length: 0\r\n\r\n"),
4871 MockWrite(false, OK),
4872 };
4873 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4874 arraysize(data_writes));
4875 session_deps.socket_factory.AddSocketDataProvider(&data);
4876
4877 TestCompletionCallback callback;
4878
[email protected]5a1d7ca2010-04-28 20:12:274879 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364880 EXPECT_EQ(ERR_IO_PENDING, rv);
4881
4882 rv = callback.WaitForResult();
4883 EXPECT_EQ(OK, rv);
4884
4885 const HttpResponseInfo* response = trans->GetResponseInfo();
4886 EXPECT_TRUE(response != NULL);
4887 EXPECT_TRUE(response->headers != NULL);
4888 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
4889
4890 file_util::Delete(temp_file, false);
4891}
4892
4893TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
4894 SessionDependencies session_deps;
4895 scoped_ptr<HttpTransaction> trans(
4896 new HttpNetworkTransaction(CreateSession(&session_deps)));
4897
4898 FilePath temp_file;
4899 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
4900 std::string temp_file_contents("Unreadable file.");
4901 std::string unreadable_contents(temp_file_contents.length(), '\0');
4902 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
4903 temp_file_contents.length()));
4904
4905 HttpRequestInfo request;
4906 request.method = "POST";
4907 request.url = GURL("http://www.google.com/upload");
4908 request.upload_data = new UploadData;
4909 request.load_flags = 0;
4910
4911 std::vector<UploadData::Element> elements;
4912 UploadData::Element element;
4913 element.SetToFilePath(temp_file);
4914 elements.push_back(element);
4915 request.upload_data->set_elements(elements);
4916
4917 MockRead data_reads[] = {
4918 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
4919 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4920 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
4921
4922 MockRead("HTTP/1.1 200 OK\r\n"),
4923 MockRead("Content-Length: 0\r\n\r\n"),
4924 MockRead(false, OK),
4925 };
4926 MockWrite data_writes[] = {
4927 MockWrite("POST /upload HTTP/1.1\r\n"
4928 "Host: www.google.com\r\n"
4929 "Connection: keep-alive\r\n"
4930 "Content-Length: 16\r\n\r\n"),
4931 MockWrite(false, temp_file_contents.c_str()),
4932
4933 MockWrite("POST /upload HTTP/1.1\r\n"
4934 "Host: www.google.com\r\n"
4935 "Connection: keep-alive\r\n"
4936 "Content-Length: 16\r\n"
4937 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4938 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
4939 MockWrite(false, OK),
4940 };
4941 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
4942 arraysize(data_writes));
4943 session_deps.socket_factory.AddSocketDataProvider(&data);
4944
4945 TestCompletionCallback callback1;
4946
[email protected]5a1d7ca2010-04-28 20:12:274947 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:364948 EXPECT_EQ(ERR_IO_PENDING, rv);
4949
4950 rv = callback1.WaitForResult();
4951 EXPECT_EQ(OK, rv);
4952
4953 const HttpResponseInfo* response = trans->GetResponseInfo();
4954 EXPECT_TRUE(response != NULL);
4955 EXPECT_TRUE(response->headers != NULL);
4956 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
4957
4958 // The password prompt info should have been set in response->auth_challenge.
4959 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4960 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4961 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4962 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4963
4964 // Now make the file unreadable and try again.
4965 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
4966
4967 TestCompletionCallback callback2;
4968
[email protected]13c8a092010-07-29 06:15:444969 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:364970 EXPECT_EQ(ERR_IO_PENDING, rv);
4971
4972 rv = callback2.WaitForResult();
4973 EXPECT_EQ(OK, rv);
4974
4975 response = trans->GetResponseInfo();
4976 EXPECT_TRUE(response != NULL);
4977 EXPECT_TRUE(response->headers != NULL);
4978 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4979 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
4980
4981 file_util::Delete(temp_file, false);
4982}
4983
[email protected]aeefc9e82010-02-19 16:18:274984// Tests that changes to Auth realms are treated like auth rejections.
4985TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
4986 SessionDependencies session_deps;
4987 scoped_ptr<HttpTransaction> trans(
4988 new HttpNetworkTransaction(CreateSession(&session_deps)));
4989
4990 HttpRequestInfo request;
4991 request.method = "GET";
4992 request.url = GURL("http://www.google.com/");
4993 request.load_flags = 0;
4994
4995 // First transaction will request a resource and receive a Basic challenge
4996 // with realm="first_realm".
4997 MockWrite data_writes1[] = {
4998 MockWrite("GET / HTTP/1.1\r\n"
4999 "Host: www.google.com\r\n"
5000 "Connection: keep-alive\r\n"
5001 "\r\n"),
5002 };
5003 MockRead data_reads1[] = {
5004 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5005 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5006 "\r\n"),
5007 };
5008
5009 // After calling trans->RestartWithAuth(), provide an Authentication header
5010 // for first_realm. The server will reject and provide a challenge with
5011 // second_realm.
5012 MockWrite data_writes2[] = {
5013 MockWrite("GET / HTTP/1.1\r\n"
5014 "Host: www.google.com\r\n"
5015 "Connection: keep-alive\r\n"
5016 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5017 "\r\n"),
5018 };
5019 MockRead data_reads2[] = {
5020 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5021 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5022 "\r\n"),
5023 };
5024
5025 // This again fails, and goes back to first_realm. Make sure that the
5026 // entry is removed from cache.
5027 MockWrite data_writes3[] = {
5028 MockWrite("GET / HTTP/1.1\r\n"
5029 "Host: www.google.com\r\n"
5030 "Connection: keep-alive\r\n"
5031 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5032 "\r\n"),
5033 };
5034 MockRead data_reads3[] = {
5035 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5036 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5037 "\r\n"),
5038 };
5039
5040 // Try one last time (with the correct password) and get the resource.
5041 MockWrite data_writes4[] = {
5042 MockWrite("GET / HTTP/1.1\r\n"
5043 "Host: www.google.com\r\n"
5044 "Connection: keep-alive\r\n"
5045 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5046 "\r\n"),
5047 };
5048 MockRead data_reads4[] = {
5049 MockRead("HTTP/1.1 200 OK\r\n"
5050 "Content-Type: text/html; charset=iso-8859-1\r\n"
5051 "Content-Length: 100\r\n"
5052 "\r\n"),
5053 };
5054
5055 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5056 data_writes1, arraysize(data_writes1));
5057 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5058 data_writes2, arraysize(data_writes2));
5059 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5060 data_writes3, arraysize(data_writes3));
5061 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5062 data_writes4, arraysize(data_writes4));
5063 session_deps.socket_factory.AddSocketDataProvider(&data1);
5064 session_deps.socket_factory.AddSocketDataProvider(&data2);
5065 session_deps.socket_factory.AddSocketDataProvider(&data3);
5066 session_deps.socket_factory.AddSocketDataProvider(&data4);
5067
5068 TestCompletionCallback callback1;
5069
5070 // Issue the first request with Authorize headers. There should be a
5071 // password prompt for first_realm waiting to be filled in after the
5072 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275073 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275074 EXPECT_EQ(ERR_IO_PENDING, rv);
5075 rv = callback1.WaitForResult();
5076 EXPECT_EQ(OK, rv);
5077 const HttpResponseInfo* response = trans->GetResponseInfo();
5078 ASSERT_FALSE(response == NULL);
5079 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5080 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5081 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5082 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5083
5084 // Issue the second request with an incorrect password. There should be a
5085 // password prompt for second_realm waiting to be filled in after the
5086 // transaction completes.
5087 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445088 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275089 EXPECT_EQ(ERR_IO_PENDING, rv);
5090 rv = callback2.WaitForResult();
5091 EXPECT_EQ(OK, rv);
5092 response = trans->GetResponseInfo();
5093 ASSERT_FALSE(response == NULL);
5094 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5095 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5096 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5097 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5098
5099 // Issue the third request with another incorrect password. There should be
5100 // a password prompt for first_realm waiting to be filled in. If the password
5101 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5102 // first_realm was not correctly removed.
5103 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445104 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275105 EXPECT_EQ(ERR_IO_PENDING, rv);
5106 rv = callback3.WaitForResult();
5107 EXPECT_EQ(OK, rv);
5108 response = trans->GetResponseInfo();
5109 ASSERT_FALSE(response == NULL);
5110 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5111 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5112 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5113 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5114
5115 // Issue the fourth request with the correct password and username.
5116 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445117 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275118 EXPECT_EQ(ERR_IO_PENDING, rv);
5119 rv = callback4.WaitForResult();
5120 EXPECT_EQ(OK, rv);
5121 response = trans->GetResponseInfo();
5122 ASSERT_FALSE(response == NULL);
5123 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5124}
5125
[email protected]564b4912010-03-09 16:30:425126TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]a2cb8122010-03-10 17:22:425127 HttpNetworkTransaction::SetNextProtos("needs_to_be_set_for_this_test");
[email protected]31e2c69e2010-04-15 18:06:065128 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]a2cb8122010-03-10 17:22:425129
[email protected]564b4912010-03-09 16:30:425130 SessionDependencies session_deps;
5131
5132 MockRead data_reads[] = {
5133 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355134 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425135 MockRead("hello world"),
5136 MockRead(false, OK),
5137 };
5138
5139 HttpRequestInfo request;
5140 request.method = "GET";
5141 request.url = GURL("http://www.google.com/");
5142 request.load_flags = 0;
5143
5144 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5145
5146 session_deps.socket_factory.AddSocketDataProvider(&data);
5147
5148 TestCompletionCallback callback;
5149
5150 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5151 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5152
[email protected]5a1d7ca2010-04-28 20:12:275153 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425154 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535155
[email protected]2fbaecf22010-07-22 22:20:355156 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425157 const HttpAlternateProtocols& alternate_protocols =
5158 session->alternate_protocols();
5159 EXPECT_FALSE(
5160 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5161
5162 EXPECT_EQ(OK, callback.WaitForResult());
5163
5164 const HttpResponseInfo* response = trans->GetResponseInfo();
5165 ASSERT_TRUE(response != NULL);
5166 ASSERT_TRUE(response->headers != NULL);
5167 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535168 EXPECT_FALSE(response->was_fetched_via_spdy);
5169 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575170 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425171
5172 std::string response_data;
5173 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5174 EXPECT_EQ("hello world", response_data);
5175
5176 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5177 const HttpAlternateProtocols::PortProtocolPair alternate =
5178 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5179 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5180 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355181 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425182 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425183
[email protected]31e2c69e2010-04-15 18:06:065184 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]a2cb8122010-03-10 17:22:425185 HttpNetworkTransaction::SetNextProtos("");
[email protected]564b4912010-03-09 16:30:425186}
5187
5188TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]31e2c69e2010-04-15 18:06:065189 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]564b4912010-03-09 16:30:425190 SessionDependencies session_deps;
5191
5192 HttpRequestInfo request;
5193 request.method = "GET";
5194 request.url = GURL("http://www.google.com/");
5195 request.load_flags = 0;
5196
5197 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5198 StaticSocketDataProvider first_data;
5199 first_data.set_connect_data(mock_connect);
5200 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5201
5202 MockRead data_reads[] = {
5203 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5204 MockRead("hello world"),
5205 MockRead(true, OK),
5206 };
5207 StaticSocketDataProvider second_data(
5208 data_reads, arraysize(data_reads), NULL, 0);
5209 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5210
5211 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5212 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5213 // http://crbug.com/37454.
5214 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5215
5216 TestCompletionCallback callback;
5217
5218 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5219
[email protected]2fbaecf22010-07-22 22:20:355220 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425221 HttpAlternateProtocols* alternate_protocols =
5222 session->mutable_alternate_protocols();
5223 alternate_protocols->SetAlternateProtocolFor(
5224 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355225 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425226
5227 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5228
[email protected]5a1d7ca2010-04-28 20:12:275229 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425230 EXPECT_EQ(ERR_IO_PENDING, rv);
5231 EXPECT_EQ(OK, callback.WaitForResult());
5232
5233 const HttpResponseInfo* response = trans->GetResponseInfo();
5234 ASSERT_TRUE(response != NULL);
5235 ASSERT_TRUE(response->headers != NULL);
5236 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5237
5238 std::string response_data;
5239 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5240 EXPECT_EQ("hello world", response_data);
5241
5242 ASSERT_TRUE(
5243 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5244 const HttpAlternateProtocols::PortProtocolPair alternate =
5245 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5246 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]31e2c69e2010-04-15 18:06:065247 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425248}
5249
5250// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5251// says that it does SPDY, but it just does the TLS handshake, but the NPN
5252// response does not indicate SPDY, so we just do standard HTTPS over the port.
5253// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5254// on the original port.
[email protected]a2cb8122010-03-10 17:22:425255// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5256// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535257//
[email protected]a2cb8122010-03-10 17:22:425258// HttpRequestInfo request;
5259// request.method = "GET";
5260// request.url = GURL("http://www.google.com/");
5261// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535262//
[email protected]a2cb8122010-03-10 17:22:425263// MockRead data_reads[] = {
5264// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5265// MockRead("hello world"),
5266// MockRead(true, OK),
5267// };
5268// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5269// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535270//
[email protected]a2cb8122010-03-10 17:22:425271// SSLSocketDataProvider ssl(true, OK);
5272// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535273//
[email protected]a2cb8122010-03-10 17:22:425274// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535275//
[email protected]a2cb8122010-03-10 17:22:425276// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535277//
[email protected]a2cb8122010-03-10 17:22:425278// HostPortPair http_host_port_pair;
5279// http_host_port_pair.host = "www.google.com";
5280// http_host_port_pair.port = 80;
5281// HttpAlternateProtocols* alternate_protocols =
5282// session->mutable_alternate_protocols();
5283// alternate_protocols->SetAlternateProtocolFor(
5284// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065285// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535286//
[email protected]a2cb8122010-03-10 17:22:425287// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535288//
[email protected]5a1d7ca2010-04-28 20:12:275289// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425290// EXPECT_EQ(ERR_IO_PENDING, rv);
5291// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535292//
[email protected]a2cb8122010-03-10 17:22:425293// const HttpResponseInfo* response = trans->GetResponseInfo();
5294// ASSERT_TRUE(response != NULL);
5295// ASSERT_TRUE(response->headers != NULL);
5296// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535297//
[email protected]a2cb8122010-03-10 17:22:425298// std::string response_data;
5299// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5300// EXPECT_EQ("hello world", response_data);
5301// }
5302
5303TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]31e2c69e2010-04-15 18:06:065304 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355305 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425306 SessionDependencies session_deps;
5307
5308 HttpRequestInfo request;
5309 request.method = "GET";
5310 request.url = GURL("http://www.google.com/");
5311 request.load_flags = 0;
5312
[email protected]a2cb8122010-03-10 17:22:425313 StaticSocketDataProvider first_tcp_connect;
5314 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5315
5316 SSLSocketDataProvider ssl(true, OK);
5317 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5318
[email protected]564b4912010-03-09 16:30:425319 MockRead data_reads[] = {
5320 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5321 MockRead("hello world"),
5322 MockRead(true, OK),
5323 };
[email protected]a2cb8122010-03-10 17:22:425324 StaticSocketDataProvider fallback_data(
5325 data_reads, arraysize(data_reads), NULL, 0);
5326 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425327
5328 TestCompletionCallback callback;
5329
5330 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5331
[email protected]2fbaecf22010-07-22 22:20:355332 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425333 HttpAlternateProtocols* alternate_protocols =
5334 session->mutable_alternate_protocols();
5335 alternate_protocols->SetAlternateProtocolFor(
5336 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355337 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425338
5339 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5340
[email protected]5a1d7ca2010-04-28 20:12:275341 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425342 EXPECT_EQ(ERR_IO_PENDING, rv);
5343 EXPECT_EQ(OK, callback.WaitForResult());
5344
5345 const HttpResponseInfo* response = trans->GetResponseInfo();
5346 ASSERT_TRUE(response != NULL);
5347 ASSERT_TRUE(response->headers != NULL);
5348 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5349
5350 std::string response_data;
5351 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5352 EXPECT_EQ("hello world", response_data);
[email protected]2ff8b312010-04-26 22:20:545353 HttpNetworkTransaction::SetNextProtos("");
5354 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5355}
5356
5357TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
5358 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355359 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545360 SessionDependencies session_deps;
5361
5362 HttpRequestInfo request;
5363 request.method = "GET";
5364 request.url = GURL("http://www.google.com/");
5365 request.load_flags = 0;
5366
5367 MockRead data_reads[] = {
5368 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355369 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545370 MockRead("hello world"),
5371 MockRead(true, OK),
5372 };
5373
5374 StaticSocketDataProvider first_transaction(
5375 data_reads, arraysize(data_reads), NULL, 0);
5376 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5377
5378 SSLSocketDataProvider ssl(true, OK);
5379 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355380 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535381 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545382 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5383
[email protected]2bd93022010-07-17 00:58:445384 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135385 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545386
[email protected]2bd93022010-07-17 00:58:445387 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5388 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545389 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135390 CreateMockRead(*resp),
5391 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545392 MockRead(true, 0, 0),
5393 };
5394
5395 scoped_refptr<DelayedSocketData> spdy_data(
5396 new DelayedSocketData(
5397 1, // wait for one write to finish before reading.
5398 spdy_reads, arraysize(spdy_reads),
5399 spdy_writes, arraysize(spdy_writes)));
5400 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5401
5402 TestCompletionCallback callback;
5403
5404 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5405 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5406
[email protected]5a1d7ca2010-04-28 20:12:275407 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545408 EXPECT_EQ(ERR_IO_PENDING, rv);
5409 EXPECT_EQ(OK, callback.WaitForResult());
5410
5411 const HttpResponseInfo* response = trans->GetResponseInfo();
5412 ASSERT_TRUE(response != NULL);
5413 ASSERT_TRUE(response->headers != NULL);
5414 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5415
5416 std::string response_data;
5417 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5418 EXPECT_EQ("hello world", response_data);
5419
5420 trans.reset(new HttpNetworkTransaction(session));
5421
[email protected]5a1d7ca2010-04-28 20:12:275422 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545423 EXPECT_EQ(ERR_IO_PENDING, rv);
5424 EXPECT_EQ(OK, callback.WaitForResult());
5425
5426 response = trans->GetResponseInfo();
5427 ASSERT_TRUE(response != NULL);
5428 ASSERT_TRUE(response->headers != NULL);
5429 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535430 EXPECT_TRUE(response->was_fetched_via_spdy);
5431 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575432 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545433
5434 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5435 EXPECT_EQ("hello!", response_data);
5436
5437 HttpNetworkTransaction::SetNextProtos("");
5438 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5439}
5440
[email protected]631f1322010-04-30 17:59:115441class CapturingProxyResolver : public ProxyResolver {
5442 public:
5443 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
5444 virtual ~CapturingProxyResolver() {}
5445
5446 virtual int GetProxyForURL(const GURL& url,
5447 ProxyInfo* results,
5448 CompletionCallback* callback,
5449 RequestHandle* request,
5450 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:405451 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
5452 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:425453 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:115454 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:425455 return OK;
[email protected]631f1322010-04-30 17:59:115456 }
5457
5458 virtual void CancelRequest(RequestHandle request) {
5459 NOTREACHED();
5460 }
5461
[email protected]24476402010-07-20 20:55:175462 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:115463 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:425464 return OK;
[email protected]631f1322010-04-30 17:59:115465 }
5466
[email protected]24476402010-07-20 20:55:175467 const std::vector<GURL>& resolved() const { return resolved_; }
5468
5469 private:
[email protected]631f1322010-04-30 17:59:115470 std::vector<GURL> resolved_;
5471
5472 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
5473};
5474
[email protected]631f1322010-04-30 17:59:115475TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
5476 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355477 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:115478
5479 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:425480 proxy_config.set_auto_detect(true);
5481 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:115482
[email protected]631f1322010-04-30 17:59:115483 CapturingProxyResolver* capturing_proxy_resolver =
5484 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:385485 SessionDependencies session_deps(new ProxyService(
5486 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
5487 NULL));
[email protected]631f1322010-04-30 17:59:115488
5489 HttpRequestInfo request;
5490 request.method = "GET";
5491 request.url = GURL("http://www.google.com/");
5492 request.load_flags = 0;
5493
5494 MockRead data_reads[] = {
5495 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355496 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:115497 MockRead("hello world"),
5498 MockRead(true, OK),
5499 };
5500
5501 StaticSocketDataProvider first_transaction(
5502 data_reads, arraysize(data_reads), NULL, 0);
5503 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5504
5505 SSLSocketDataProvider ssl(true, OK);
5506 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355507 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535508 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:115509 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5510
[email protected]2bd93022010-07-17 00:58:445511 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:115512 MockWrite spdy_writes[] = {
5513 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5514 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:425515 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:135516 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:115517 };
5518
[email protected]d911f1b2010-05-05 22:39:425519 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
5520
[email protected]2bd93022010-07-17 00:58:445521 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5522 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:115523 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:425524 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:135525 CreateMockRead(*resp.get(), 4), // 2, 4
5526 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:425527 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:115528 };
5529
[email protected]d911f1b2010-05-05 22:39:425530 scoped_refptr<OrderedSocketData> spdy_data(
5531 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:115532 spdy_reads, arraysize(spdy_reads),
5533 spdy_writes, arraysize(spdy_writes)));
5534 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5535
5536 TestCompletionCallback callback;
5537
5538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5539 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5540
5541 int rv = trans->Start(&request, &callback, BoundNetLog());
5542 EXPECT_EQ(ERR_IO_PENDING, rv);
5543 EXPECT_EQ(OK, callback.WaitForResult());
5544
5545 const HttpResponseInfo* response = trans->GetResponseInfo();
5546 ASSERT_TRUE(response != NULL);
5547 ASSERT_TRUE(response->headers != NULL);
5548 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535549 EXPECT_FALSE(response->was_fetched_via_spdy);
5550 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115551
5552 std::string response_data;
5553 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5554 EXPECT_EQ("hello world", response_data);
5555
5556 trans.reset(new HttpNetworkTransaction(session));
5557
5558 rv = trans->Start(&request, &callback, BoundNetLog());
5559 EXPECT_EQ(ERR_IO_PENDING, rv);
5560 EXPECT_EQ(OK, callback.WaitForResult());
5561
5562 response = trans->GetResponseInfo();
5563 ASSERT_TRUE(response != NULL);
5564 ASSERT_TRUE(response->headers != NULL);
5565 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535566 EXPECT_TRUE(response->was_fetched_via_spdy);
5567 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:115568
5569 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5570 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:425571 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
5572 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:115573 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:425574 EXPECT_EQ("https://www.google.com/",
5575 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:115576
5577 HttpNetworkTransaction::SetNextProtos("");
5578 HttpNetworkTransaction::SetUseAlternateProtocols(false);
5579}
[email protected]631f1322010-04-30 17:59:115580
[email protected]2ff8b312010-04-26 22:20:545581TEST_F(HttpNetworkTransactionTest,
5582 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
5583 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:355584 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545585 SessionDependencies session_deps;
5586
5587 HttpRequestInfo request;
5588 request.method = "GET";
5589 request.url = GURL("http://www.google.com/");
5590 request.load_flags = 0;
5591
5592 MockRead data_reads[] = {
5593 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355594 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545595 MockRead("hello world"),
5596 MockRead(true, OK),
5597 };
5598
5599 StaticSocketDataProvider first_transaction(
5600 data_reads, arraysize(data_reads), NULL, 0);
5601 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5602
5603 SSLSocketDataProvider ssl(true, OK);
5604 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355605 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535606 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545607 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:535608 // Make sure we use ssl for spdy here.
5609 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:545610
[email protected]2bd93022010-07-17 00:58:445611 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135612 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:545613
[email protected]2bd93022010-07-17 00:58:445614 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
5615 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:545616 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:135617 CreateMockRead(*resp),
5618 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:545619 MockRead(true, 0, 0),
5620 };
5621
5622 scoped_refptr<DelayedSocketData> spdy_data(
5623 new DelayedSocketData(
5624 1, // wait for one write to finish before reading.
5625 spdy_reads, arraysize(spdy_reads),
5626 spdy_writes, arraysize(spdy_writes)));
5627 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
5628
5629 TestCompletionCallback callback;
5630
5631 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5632
5633 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
5634
[email protected]5a1d7ca2010-04-28 20:12:275635 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545636 EXPECT_EQ(ERR_IO_PENDING, rv);
5637 EXPECT_EQ(OK, callback.WaitForResult());
5638
5639 const HttpResponseInfo* response = trans->GetResponseInfo();
5640 ASSERT_TRUE(response != NULL);
5641 ASSERT_TRUE(response->headers != NULL);
5642 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5643
5644 std::string response_data;
5645 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5646 EXPECT_EQ("hello world", response_data);
5647
5648 // Set up an initial SpdySession in the pool to reuse.
[email protected]b261d0e2010-08-02 19:13:245649 HostPortProxyPair pair(HostPortPair("www.google.com", 443), "DIRECT");
[email protected]2ff8b312010-04-26 22:20:545650 scoped_refptr<SpdySession> spdy_session =
[email protected]b261d0e2010-08-02 19:13:245651 session->spdy_session_pool()->Get(pair, session, BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:215652 scoped_refptr<TCPSocketParams> tcp_params =
5653 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]635909f2010-05-12 18:19:365654 spdy_session->Connect("www.google.com:443", tcp_params, MEDIUM);
[email protected]2ff8b312010-04-26 22:20:545655 trans.reset(new HttpNetworkTransaction(session));
5656
[email protected]5a1d7ca2010-04-28 20:12:275657 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:545658 EXPECT_EQ(ERR_IO_PENDING, rv);
5659 EXPECT_EQ(OK, callback.WaitForResult());
5660
5661 response = trans->GetResponseInfo();
5662 ASSERT_TRUE(response != NULL);
5663 ASSERT_TRUE(response->headers != NULL);
5664 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535665 EXPECT_TRUE(response->was_fetched_via_spdy);
5666 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575667 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:545668
5669 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5670 EXPECT_EQ("hello!", response_data);
5671
5672 HttpNetworkTransaction::SetNextProtos("");
[email protected]31e2c69e2010-04-15 18:06:065673 HttpNetworkTransaction::SetUseAlternateProtocols(false);
[email protected]564b4912010-03-09 16:30:425674}
5675
[email protected]044de0642010-06-17 10:42:155676// GenerateAuthToken is a mighty big test.
5677// It tests all permutation of GenerateAuthToken behavior:
5678// - Synchronous and Asynchronous completion.
5679// - OK or error on completion.
5680// - Direct connection, non-authenticating proxy, and authenticating proxy.
5681// - HTTP or HTTPS backend (to include proxy tunneling).
5682// - Non-authenticating and authenticating backend.
5683//
5684// In all, there are 44 reasonable permuations (for example, if there are
5685// problems generating an auth token for an authenticating proxy, we don't
5686// need to test all permutations of the backend server).
5687//
5688// The test proceeds by going over each of the configuration cases, and
5689// potentially running up to three rounds in each of the tests. The TestConfig
5690// specifies both the configuration for the test as well as the expectations
5691// for the results.
5692TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
5693 const char* kServer = "http://www.example.com";
5694 const char* kSecureServer = "https://www.example.com";
5695 const char* kProxy = "myproxy:70";
5696 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
5697
5698 enum AuthTiming {
5699 AUTH_NONE,
5700 AUTH_SYNC,
5701 AUTH_ASYNC,
5702 };
5703
5704 const MockWrite kGet(
5705 "GET / HTTP/1.1\r\n"
5706 "Host: www.example.com\r\n"
5707 "Connection: keep-alive\r\n\r\n");
5708 const MockWrite kGetProxy(
5709 "GET http://www.example.com/ HTTP/1.1\r\n"
5710 "Host: www.example.com\r\n"
5711 "Proxy-Connection: keep-alive\r\n\r\n");
5712 const MockWrite kGetAuth(
5713 "GET / HTTP/1.1\r\n"
5714 "Host: www.example.com\r\n"
5715 "Connection: keep-alive\r\n"
5716 "Authorization: auth_token\r\n\r\n");
5717 const MockWrite kGetProxyAuth(
5718 "GET http://www.example.com/ HTTP/1.1\r\n"
5719 "Host: www.example.com\r\n"
5720 "Proxy-Connection: keep-alive\r\n"
5721 "Proxy-Authorization: auth_token\r\n\r\n");
5722 const MockWrite kGetAuthThroughProxy(
5723 "GET http://www.example.com/ HTTP/1.1\r\n"
5724 "Host: www.example.com\r\n"
5725 "Proxy-Connection: keep-alive\r\n"
5726 "Authorization: auth_token\r\n\r\n");
5727 const MockWrite kGetAuthWithProxyAuth(
5728 "GET http://www.example.com/ HTTP/1.1\r\n"
5729 "Host: www.example.com\r\n"
5730 "Proxy-Connection: keep-alive\r\n"
5731 "Proxy-Authorization: auth_token\r\n"
5732 "Authorization: auth_token\r\n\r\n");
5733 const MockWrite kConnect(
5734 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5735 "Host: www.example.com\r\n"
5736 "Proxy-Connection: keep-alive\r\n\r\n");
5737 const MockWrite kConnectProxyAuth(
5738 "CONNECT www.example.com:443 HTTP/1.1\r\n"
5739 "Host: www.example.com\r\n"
5740 "Proxy-Connection: keep-alive\r\n"
5741 "Proxy-Authorization: auth_token\r\n\r\n");
5742
5743 const MockRead kSuccess(
5744 "HTTP/1.1 200 OK\r\n"
5745 "Content-Type: text/html; charset=iso-8859-1\r\n"
5746 "Content-Length: 3\r\n\r\n"
5747 "Yes");
5748 const MockRead kFailure(
5749 "Should not be called.");
5750 const MockRead kServerChallenge(
5751 "HTTP/1.1 401 Unauthorized\r\n"
5752 "WWW-Authenticate: Mock realm=server\r\n"
5753 "Content-Type: text/html; charset=iso-8859-1\r\n"
5754 "Content-Length: 14\r\n\r\n"
5755 "Unauthorized\r\n");
5756 const MockRead kProxyChallenge(
5757 "HTTP/1.1 407 Unauthorized\r\n"
5758 "Proxy-Authenticate: Mock realm=proxy\r\n"
5759 "Proxy-Connection: close\r\n"
5760 "Content-Type: text/html; charset=iso-8859-1\r\n"
5761 "Content-Length: 14\r\n\r\n"
5762 "Unauthorized\r\n");
5763 const MockRead kProxyConnected(
5764 "HTTP/1.1 200 Connection Established\r\n\r\n");
5765
5766 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
5767 // no constructors, but the C++ compiler on Windows warns about
5768 // unspecified data in compound literals. So, moved to using constructors,
5769 // and TestRound's created with the default constructor should not be used.
5770 struct TestRound {
5771 TestRound()
5772 : expected_rv(ERR_UNEXPECTED),
5773 extra_write(NULL),
5774 extra_read(NULL) {
5775 }
5776 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5777 int expected_rv_arg)
5778 : write(write_arg),
5779 read(read_arg),
5780 expected_rv(expected_rv_arg),
5781 extra_write(NULL),
5782 extra_read(NULL) {
5783 }
5784 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
5785 int expected_rv_arg, const MockWrite* extra_write_arg,
5786 const MockWrite* extra_read_arg)
5787 : write(write_arg),
5788 read(read_arg),
5789 expected_rv(expected_rv_arg),
5790 extra_write(extra_write_arg),
5791 extra_read(extra_read_arg) {
5792 }
5793 MockWrite write;
5794 MockRead read;
5795 int expected_rv;
5796 const MockWrite* extra_write;
5797 const MockRead* extra_read;
5798 };
5799
5800 static const int kNoSSL = 500;
5801
5802 struct TestConfig {
5803 const char* proxy_url;
5804 AuthTiming proxy_auth_timing;
5805 int proxy_auth_rv;
5806 const char* server_url;
5807 AuthTiming server_auth_timing;
5808 int server_auth_rv;
5809 int num_auth_rounds;
5810 int first_ssl_round;
5811 TestRound rounds[3];
5812 } test_configs[] = {
5813 // Non-authenticating HTTP server with a direct connection.
5814 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5815 { TestRound(kGet, kSuccess, OK)}},
5816 // Authenticating HTTP server with a direct connection.
5817 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5818 { TestRound(kGet, kServerChallenge, OK),
5819 TestRound(kGetAuth, kSuccess, OK)}},
5820 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5821 { TestRound(kGet, kServerChallenge, OK),
5822 TestRound(kGetAuth, kFailure, kAuthErr)}},
5823 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5824 { TestRound(kGet, kServerChallenge, OK),
5825 TestRound(kGetAuth, kSuccess, OK)}},
5826 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5827 { TestRound(kGet, kServerChallenge, OK),
5828 TestRound(kGetAuth, kFailure, kAuthErr)}},
5829 // Non-authenticating HTTP server through a non-authenticating proxy.
5830 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
5831 { TestRound(kGetProxy, kSuccess, OK)}},
5832 // Authenticating HTTP server through a non-authenticating proxy.
5833 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
5834 { TestRound(kGetProxy, kServerChallenge, OK),
5835 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5836 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
5837 { TestRound(kGetProxy, kServerChallenge, OK),
5838 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5839 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
5840 { TestRound(kGetProxy, kServerChallenge, OK),
5841 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
5842 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
5843 { TestRound(kGetProxy, kServerChallenge, OK),
5844 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
5845 // Non-authenticating HTTP server through an authenticating proxy.
5846 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5847 { TestRound(kGetProxy, kProxyChallenge, OK),
5848 TestRound(kGetProxyAuth, kSuccess, OK)}},
5849 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5850 { TestRound(kGetProxy, kProxyChallenge, OK),
5851 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5852 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
5853 { TestRound(kGetProxy, kProxyChallenge, OK),
5854 TestRound(kGetProxyAuth, kSuccess, OK)}},
5855 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
5856 { TestRound(kGetProxy, kProxyChallenge, OK),
5857 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
5858 // Authenticating HTTP server through an authenticating proxy.
5859 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5860 { TestRound(kGetProxy, kProxyChallenge, OK),
5861 TestRound(kGetProxyAuth, kServerChallenge, OK),
5862 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5863 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5864 { TestRound(kGetProxy, kProxyChallenge, OK),
5865 TestRound(kGetProxyAuth, kServerChallenge, OK),
5866 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5867 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
5868 { TestRound(kGetProxy, kProxyChallenge, OK),
5869 TestRound(kGetProxyAuth, kServerChallenge, OK),
5870 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5871 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
5872 { TestRound(kGetProxy, kProxyChallenge, OK),
5873 TestRound(kGetProxyAuth, kServerChallenge, OK),
5874 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5875 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5876 { TestRound(kGetProxy, kProxyChallenge, OK),
5877 TestRound(kGetProxyAuth, kServerChallenge, OK),
5878 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5879 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5880 { TestRound(kGetProxy, kProxyChallenge, OK),
5881 TestRound(kGetProxyAuth, kServerChallenge, OK),
5882 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5883 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
5884 { TestRound(kGetProxy, kProxyChallenge, OK),
5885 TestRound(kGetProxyAuth, kServerChallenge, OK),
5886 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
5887 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
5888 { TestRound(kGetProxy, kProxyChallenge, OK),
5889 TestRound(kGetProxyAuth, kServerChallenge, OK),
5890 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
5891 // Non-authenticating HTTPS server with a direct connection.
5892 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5893 { TestRound(kGet, kSuccess, OK)}},
5894 // Authenticating HTTPS server with a direct connection.
5895 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5896 { TestRound(kGet, kServerChallenge, OK),
5897 TestRound(kGetAuth, kSuccess, OK)}},
5898 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5899 { TestRound(kGet, kServerChallenge, OK),
5900 TestRound(kGetAuth, kFailure, kAuthErr)}},
5901 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5902 { TestRound(kGet, kServerChallenge, OK),
5903 TestRound(kGetAuth, kSuccess, OK)}},
5904 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5905 { TestRound(kGet, kServerChallenge, OK),
5906 TestRound(kGetAuth, kFailure, kAuthErr)}},
5907 // Non-authenticating HTTPS server with a non-authenticating proxy.
5908 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
5909 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
5910 // Authenticating HTTPS server through a non-authenticating proxy.
5911 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
5912 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5913 TestRound(kGetAuth, kSuccess, OK)}},
5914 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
5915 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5916 TestRound(kGetAuth, kFailure, kAuthErr)}},
5917 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
5918 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5919 TestRound(kGetAuth, kSuccess, OK)}},
5920 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
5921 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
5922 TestRound(kGetAuth, kFailure, kAuthErr)}},
5923 // Non-Authenticating HTTPS server through an authenticating proxy.
5924 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5925 { TestRound(kConnect, kProxyChallenge, OK),
5926 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5927 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5928 { TestRound(kConnect, kProxyChallenge, OK),
5929 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5930 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
5931 { TestRound(kConnect, kProxyChallenge, OK),
5932 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
5933 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
5934 { TestRound(kConnect, kProxyChallenge, OK),
5935 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
5936 // Authenticating HTTPS server through an authenticating proxy.
5937 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5938 { TestRound(kConnect, kProxyChallenge, OK),
5939 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5940 &kGet, &kServerChallenge),
5941 TestRound(kGetAuth, kSuccess, OK)}},
5942 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5943 { TestRound(kConnect, kProxyChallenge, OK),
5944 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5945 &kGet, &kServerChallenge),
5946 TestRound(kGetAuth, kFailure, kAuthErr)}},
5947 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
5948 { TestRound(kConnect, kProxyChallenge, OK),
5949 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5950 &kGet, &kServerChallenge),
5951 TestRound(kGetAuth, kSuccess, OK)}},
5952 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
5953 { TestRound(kConnect, kProxyChallenge, OK),
5954 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5955 &kGet, &kServerChallenge),
5956 TestRound(kGetAuth, kFailure, kAuthErr)}},
5957 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5958 { TestRound(kConnect, kProxyChallenge, OK),
5959 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5960 &kGet, &kServerChallenge),
5961 TestRound(kGetAuth, kSuccess, OK)}},
5962 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5963 { TestRound(kConnect, kProxyChallenge, OK),
5964 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5965 &kGet, &kServerChallenge),
5966 TestRound(kGetAuth, kFailure, kAuthErr)}},
5967 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
5968 { TestRound(kConnect, kProxyChallenge, OK),
5969 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5970 &kGet, &kServerChallenge),
5971 TestRound(kGetAuth, kSuccess, OK)}},
5972 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
5973 { TestRound(kConnect, kProxyChallenge, OK),
5974 TestRound(kConnectProxyAuth, kProxyConnected, OK,
5975 &kGet, &kServerChallenge),
5976 TestRound(kGetAuth, kFailure, kAuthErr)}},
5977 };
5978
5979 SessionDependencies session_deps;
5980 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]3fd9dae2010-06-21 11:39:005981 HttpAuthHandlerMock::Factory* auth_factory(
5982 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:155983 session_deps.http_auth_handler_factory.reset(auth_factory);
5984
5985 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
5986 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:265987
5988 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:155989 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:005990 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:155991 std::string auth_challenge = "Mock realm=proxy";
5992 GURL origin(test_config.proxy_url);
5993 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
5994 auth_challenge.end());
5995 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
5996 origin, BoundNetLog());
5997 auth_handler->SetGenerateExpectation(
5998 test_config.proxy_auth_timing == AUTH_ASYNC,
5999 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156000 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6001 }
6002 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006003 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156004 std::string auth_challenge = "Mock realm=server";
6005 GURL origin(test_config.server_url);
6006 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6007 auth_challenge.end());
6008 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6009 origin, BoundNetLog());
6010 auth_handler->SetGenerateExpectation(
6011 test_config.server_auth_timing == AUTH_ASYNC,
6012 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156013 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6014 }
6015 if (test_config.proxy_url) {
6016 session_deps.proxy_service =
6017 CreateFixedProxyService(test_config.proxy_url);
6018 } else {
6019 session_deps.proxy_service = ProxyService::CreateNull();
6020 }
6021
6022 HttpRequestInfo request;
6023 request.method = "GET";
6024 request.url = GURL(test_config.server_url);
6025 request.load_flags = 0;
6026
6027 scoped_ptr<HttpTransaction> trans(
6028 new HttpNetworkTransaction(CreateSession(&session_deps)));
6029
6030 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6031 const TestRound& read_write_round = test_config.rounds[round];
6032
6033 // Set up expected reads and writes.
6034 MockRead reads[2];
6035 reads[0] = read_write_round.read;
6036 size_t length_reads = 1;
6037 if (read_write_round.extra_read) {
6038 reads[1] = *read_write_round.extra_read;
6039 length_reads = 2;
6040 }
6041
6042 MockWrite writes[2];
6043 writes[0] = read_write_round.write;
6044 size_t length_writes = 1;
6045 if (read_write_round.extra_write) {
6046 writes[1] = *read_write_round.extra_write;
6047 length_writes = 2;
6048 }
6049 StaticSocketDataProvider data_provider(
6050 reads, length_reads, writes, length_writes);
6051 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6052
6053 // Add an SSL sequence if necessary.
6054 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6055 if (round >= test_config.first_ssl_round)
6056 session_deps.socket_factory.AddSSLSocketDataProvider(
6057 &ssl_socket_data_provider);
6058
6059 // Start or restart the transaction.
6060 TestCompletionCallback callback;
6061 int rv;
6062 if (round == 0) {
6063 rv = trans->Start(&request, &callback, BoundNetLog());
6064 } else {
[email protected]13c8a092010-07-29 06:15:446065 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156066 }
6067 if (rv == ERR_IO_PENDING)
6068 rv = callback.WaitForResult();
6069
6070 // Compare results with expected data.
6071 EXPECT_EQ(read_write_round.expected_rv, rv);
6072 const HttpResponseInfo* response = trans->GetResponseInfo();
6073 if (read_write_round.expected_rv == OK) {
6074 EXPECT_FALSE(response == NULL);
6075 } else {
6076 EXPECT_TRUE(response == NULL);
6077 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6078 continue;
6079 }
6080 if (round + 1 < test_config.num_auth_rounds) {
6081 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6082 } else {
6083 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6084 }
6085 }
[email protected]e5ae96a2010-04-14 20:12:456086 }
[email protected]e60e47a2010-07-14 03:37:186087
6088 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
6089 session->FlushSocketPools();
[email protected]e5ae96a2010-04-14 20:12:456090}
6091
[email protected]c871bce92010-07-15 21:51:146092TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6093 // Do multi-round authentication and make sure it works correctly.
6094 SessionDependencies session_deps;
6095 HttpAuthHandlerMock::Factory* auth_factory(
6096 new HttpAuthHandlerMock::Factory());
6097 session_deps.http_auth_handler_factory.reset(auth_factory);
6098 session_deps.proxy_service = ProxyService::CreateNull();
6099 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6100 session_deps.host_resolver->set_synchronous_mode(true);
6101
6102 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6103 auth_handler->set_connection_based(true);
6104 std::string auth_challenge = "Mock realm=server";
6105 GURL origin("http://www.example.com");
6106 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6107 auth_challenge.end());
6108 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6109 origin, BoundNetLog());
6110 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6111
6112 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6113 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6114
6115 int rv = OK;
6116 const HttpResponseInfo* response = NULL;
6117 HttpRequestInfo request;
6118 request.method = "GET";
6119 request.url = origin;
6120 request.load_flags = 0;
6121 TestCompletionCallback callback;
6122
6123 const MockWrite kGet(
6124 "GET / HTTP/1.1\r\n"
6125 "Host: www.example.com\r\n"
6126 "Connection: keep-alive\r\n\r\n");
6127 const MockWrite kGetAuth(
6128 "GET / HTTP/1.1\r\n"
6129 "Host: www.example.com\r\n"
6130 "Connection: keep-alive\r\n"
6131 "Authorization: auth_token\r\n\r\n");
6132
6133 const MockRead kServerChallenge(
6134 "HTTP/1.1 401 Unauthorized\r\n"
6135 "WWW-Authenticate: Mock realm=server\r\n"
6136 "Content-Type: text/html; charset=iso-8859-1\r\n"
6137 "Content-Length: 14\r\n\r\n"
6138 "Unauthorized\r\n");
6139 const MockRead kSuccess(
6140 "HTTP/1.1 200 OK\r\n"
6141 "Content-Type: text/html; charset=iso-8859-1\r\n"
6142 "Content-Length: 3\r\n\r\n"
6143 "Yes");
6144
6145 MockWrite writes[] = {
6146 // First round
6147 kGet,
6148 // Second round
6149 kGetAuth,
6150 // Third round
6151 kGetAuth,
6152 };
6153 MockRead reads[] = {
6154 // First round
6155 kServerChallenge,
6156 // Second round
6157 kServerChallenge,
6158 // Third round
6159 kSuccess,
6160 };
6161 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6162 writes, arraysize(writes));
6163 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6164
6165 // First round
6166 auth_handler->SetGenerateExpectation(false, OK);
6167 rv = trans->Start(&request, &callback, BoundNetLog());
6168 if (rv == ERR_IO_PENDING)
6169 rv = callback.WaitForResult();
6170 EXPECT_EQ(OK, rv);
6171 response = trans->GetResponseInfo();
6172 ASSERT_FALSE(response == NULL);
6173 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6174
6175 // Second round
6176 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446177 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146178 if (rv == ERR_IO_PENDING)
6179 rv = callback.WaitForResult();
6180 EXPECT_EQ(OK, rv);
6181 response = trans->GetResponseInfo();
6182 ASSERT_FALSE(response == NULL);
6183 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6184
6185 // Third round
6186 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446187 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146188 if (rv == ERR_IO_PENDING)
6189 rv = callback.WaitForResult();
6190 EXPECT_EQ(OK, rv);
6191 response = trans->GetResponseInfo();
6192 ASSERT_FALSE(response == NULL);
6193 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6194}
6195
[email protected]aeaca1f2010-04-20 22:05:216196class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6197 public:
[email protected]06650c52010-06-03 00:49:176198 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216199 : fail_all_(fail_all) {
6200 }
6201
6202 virtual MockRead GetNextRead() {
6203 if (fail_all_)
6204 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6205
6206 return MockRead(false /* async */,
6207 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6208 }
6209
6210 virtual MockWriteResult OnWrite(const std::string& data) {
6211 return MockWriteResult(false /* async */, data.size());
6212 }
6213
6214 void Reset() {
6215 }
6216
6217 private:
6218 const bool fail_all_;
6219};
6220
6221// Test that we restart a connection when we see a decompression failure from
6222// the peer during the handshake. (In the real world we'll restart with SSLv3
6223// and we won't offer DEFLATE in that case.)
6224TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6225 HttpRequestInfo request;
6226 request.method = "GET";
6227 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6228 request.load_flags = 0;
6229
6230 SessionDependencies session_deps;
6231 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6232 false /* fail all reads */);
6233 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6234 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116235 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216236 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6237 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6238 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6239 session_deps.socket_factory.AddSSLSocketDataProvider(
6240 &ssl_socket_data_provider1);
6241 session_deps.socket_factory.AddSSLSocketDataProvider(
6242 &ssl_socket_data_provider2);
6243
[email protected]e60e47a2010-07-14 03:37:186244 // Work around http://crbug.com/37454
6245 StaticSocketDataProvider bug37454_connection;
6246 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6247 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6248
[email protected]aeaca1f2010-04-20 22:05:216249 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6250 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6251 TestCompletionCallback callback;
6252
[email protected]5a1d7ca2010-04-28 20:12:276253 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216254 EXPECT_EQ(ERR_IO_PENDING, rv);
6255 EXPECT_EQ(OK, callback.WaitForResult());
6256
6257 const HttpResponseInfo* response = trans->GetResponseInfo();
6258 ASSERT_TRUE(response != NULL);
6259 ASSERT_TRUE(response->headers != NULL);
6260 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6261
6262 std::string response_data;
6263 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6264 EXPECT_EQ("ok.", response_data);
6265}
6266
6267// Test that we restart a connection if we get a decompression failure from the
6268// peer while reading the first bytes from the connection. This occurs when the
6269// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6270// in the handshake.
6271TEST_F(HttpNetworkTransactionTest,
6272 RestartAfterTLSDecompressionFailureWithFalseStart) {
6273 HttpRequestInfo request;
6274 request.method = "GET";
6275 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6276 request.load_flags = 0;
6277
6278 SessionDependencies session_deps;
6279 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6280 true /* fail all reads */);
6281 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6282 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6283 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6284 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6285 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6286 session_deps.socket_factory.AddSSLSocketDataProvider(
6287 &ssl_socket_data_provider1);
6288 session_deps.socket_factory.AddSSLSocketDataProvider(
6289 &ssl_socket_data_provider2);
6290
6291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6292 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6293 TestCompletionCallback callback;
6294
[email protected]5a1d7ca2010-04-28 20:12:276295 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216296 EXPECT_EQ(ERR_IO_PENDING, rv);
6297 EXPECT_EQ(OK, callback.WaitForResult());
6298
6299 const HttpResponseInfo* response = trans->GetResponseInfo();
6300 ASSERT_TRUE(response != NULL);
6301 ASSERT_TRUE(response->headers != NULL);
6302 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6303
6304 std::string response_data;
6305 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6306 EXPECT_EQ("ok.", response_data);
6307}
6308
[email protected]65041fa2010-05-21 06:56:536309// This tests the case that a request is issued via http instead of spdy after
6310// npn is negotiated.
6311TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
6312 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6313 HttpNetworkTransaction::SetNextProtos("\x08http/1.1\x07http1.1");
6314 SessionDependencies session_deps;
6315 HttpRequestInfo request;
6316 request.method = "GET";
6317 request.url = GURL("https://www.google.com/");
6318 request.load_flags = 0;
6319
6320 MockWrite data_writes[] = {
6321 MockWrite("GET / HTTP/1.1\r\n"
6322 "Host: www.google.com\r\n"
6323 "Connection: keep-alive\r\n\r\n"),
6324 };
6325
6326 MockRead data_reads[] = {
6327 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356328 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536329 MockRead("hello world"),
6330 MockRead(false, OK),
6331 };
6332
6333 SSLSocketDataProvider ssl(true, OK);
6334 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6335 ssl.next_proto = "http/1.1";
6336
6337 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6338
6339 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6340 data_writes, arraysize(data_writes));
6341 session_deps.socket_factory.AddSocketDataProvider(&data);
6342
6343 TestCompletionCallback callback;
6344
6345 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6346 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6347
6348 int rv = trans->Start(&request, &callback, BoundNetLog());
6349
6350 EXPECT_EQ(ERR_IO_PENDING, rv);
6351 EXPECT_EQ(OK, callback.WaitForResult());
6352
6353 const HttpResponseInfo* response = trans->GetResponseInfo();
6354 ASSERT_TRUE(response != NULL);
6355 ASSERT_TRUE(response->headers != NULL);
6356 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6357
6358 std::string response_data;
6359 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6360 EXPECT_EQ("hello world", response_data);
6361
6362 EXPECT_FALSE(response->was_fetched_via_spdy);
6363 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576364 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:536365
6366 HttpNetworkTransaction::SetNextProtos("");
6367 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6368}
[email protected]26ef6582010-06-24 02:30:476369
6370TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
6371 // Simulate the SSL handshake completing with an NPN negotiation
6372 // followed by an immediate server closing of the socket.
6373 // Fix crash: http://crbug.com/46369
6374 HttpNetworkTransaction::SetUseAlternateProtocols(true);
[email protected]dae22c52010-07-30 02:16:356375 HttpNetworkTransaction::SetNextProtos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:476376 SessionDependencies session_deps;
6377
6378 HttpRequestInfo request;
6379 request.method = "GET";
6380 request.url = GURL("https://www.google.com/");
6381 request.load_flags = 0;
6382
6383 SSLSocketDataProvider ssl(true, OK);
6384 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356385 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:476386 ssl.was_npn_negotiated = true;
6387 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6388
[email protected]2bd93022010-07-17 00:58:446389 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136390 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:476391
6392 MockRead spdy_reads[] = {
6393 MockRead(false, 0, 0) // Not async - return 0 immediately.
6394 };
6395
6396 scoped_refptr<DelayedSocketData> spdy_data(
6397 new DelayedSocketData(
6398 0, // don't wait in this case, immediate hangup.
6399 spdy_reads, arraysize(spdy_reads),
6400 spdy_writes, arraysize(spdy_writes)));
6401 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6402
6403 TestCompletionCallback callback;
6404
6405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6406 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6407
6408 int rv = trans->Start(&request, &callback, BoundNetLog());
6409 EXPECT_EQ(ERR_IO_PENDING, rv);
6410 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
6411
6412 HttpNetworkTransaction::SetNextProtos("");
6413 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6414}
[email protected]65d34382010-07-01 18:12:266415
[email protected]f45c1ee2010-08-03 00:54:306416TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
6417 // This test ensures that the URL passed into the proxy is upgraded
6418 // to https when doing an Alternate Protocol upgrade.
6419 HttpNetworkTransaction::SetUseAlternateProtocols(true);
6420 HttpNetworkTransaction::SetNextProtos(
6421 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
6422
6423 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
6424 HttpAuthHandlerMock::Factory* auth_factory =
6425 new HttpAuthHandlerMock::Factory();
6426 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
6427 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6428 auth_factory->set_do_init_from_challenge(true);
6429 session_deps.http_auth_handler_factory.reset(auth_factory);
6430
6431 HttpRequestInfo request;
6432 request.method = "GET";
6433 request.url = GURL("http://www.google.com");
6434 request.load_flags = 0;
6435
6436 // First round goes unauthenticated through the proxy.
6437 MockWrite data_writes_1[] = {
6438 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
6439 "Host: www.google.com\r\n"
6440 "Proxy-Connection: keep-alive\r\n"
6441 "\r\n"),
6442 };
6443 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:596444 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:306445 MockRead("HTTP/1.1 200 OK\r\n"
6446 "Alternate-Protocol: 443:npn-spdy/2\r\n"
6447 "Proxy-Connection: close\r\n"
6448 "\r\n"),
6449 };
6450 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
6451 data_writes_1, arraysize(data_writes_1));
6452
6453 // Second round tries to tunnel to www.google.com due to the
6454 // Alternate-Protocol announcement in the first round. It fails due
6455 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:596456 // After the failure, a tunnel is established to www.google.com using
6457 // Proxy-Authorization headers. There is then a SPDY request round.
6458 //
6459 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
6460 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
6461 // does a Disconnect and Connect on the same socket, rather than trying
6462 // to obtain a new one.
6463 //
6464 // NOTE: Originally, the proxy response to the second CONNECT request
6465 // simply returned another 407 so the unit test could skip the SSL connection
6466 // establishment and SPDY framing issues. Alas, the
6467 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:306468 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:596469
[email protected]f45c1ee2010-08-03 00:54:306470 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6471 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6472 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
6473
[email protected]394816e92010-08-03 07:38:596474 MockWrite data_writes_2[] = {
6475 // First connection attempt without Proxy-Authorization.
6476 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6477 "Host: www.google.com\r\n"
6478 "Proxy-Connection: keep-alive\r\n"
6479 "\r\n"),
6480
6481 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:306482 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6483 "Host: www.google.com\r\n"
6484 "Proxy-Connection: keep-alive\r\n"
6485 "Proxy-Authorization: auth_token\r\n"
6486 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:306487
[email protected]394816e92010-08-03 07:38:596488 // SPDY request
6489 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:306490 };
[email protected]394816e92010-08-03 07:38:596491 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
6492 "Proxy-Authenticate: Mock\r\n"
6493 "Proxy-Connection: close\r\n"
6494 "\r\n");
6495 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6496 MockRead data_reads_2[] = {
6497 // First connection attempt fails
6498 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
6499 MockRead(true, kRejectConnectResponse,
6500 arraysize(kRejectConnectResponse) - 1, 1),
6501
6502 // Second connection attempt passes
6503 MockRead(true, kAcceptConnectResponse,
6504 arraysize(kAcceptConnectResponse) -1, 4),
6505
6506 // SPDY response
6507 CreateMockRead(*resp.get(), 6),
6508 CreateMockRead(*data.get(), 6),
6509 MockRead(true, 0, 0, 6),
6510 };
6511 scoped_refptr<OrderedSocketData> data_2(
6512 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
6513 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:306514
6515 SSLSocketDataProvider ssl(true, OK);
6516 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6517 ssl.next_proto = "spdy/2";
6518 ssl.was_npn_negotiated = true;
6519
6520 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:596521 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:306522 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6523 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6524
6525 // First round should work and provide the Alternate-Protocol state.
6526 TestCompletionCallback callback_1;
6527 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
6528 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
6529 EXPECT_EQ(ERR_IO_PENDING, rv);
6530 EXPECT_EQ(OK, callback_1.WaitForResult());
6531
6532 // Second round should attempt a tunnel connect and get an auth challenge.
6533 TestCompletionCallback callback_2;
6534 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
6535 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
6536 EXPECT_EQ(ERR_IO_PENDING, rv);
6537 EXPECT_EQ(OK, callback_2.WaitForResult());
6538 const HttpResponseInfo* response = trans_2->GetResponseInfo();
6539 ASSERT_FALSE(response == NULL);
6540 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6541
6542 // Restart with auth. Tunnel should work and response received.
6543 TestCompletionCallback callback_3;
6544 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
6545 EXPECT_EQ(ERR_IO_PENDING, rv);
6546 EXPECT_EQ(OK, callback_3.WaitForResult());
6547
6548 // After all that work, these two lines (or actually, just the scheme) are
6549 // what this test is all about. Make sure it happens correctly.
6550 const GURL& request_url = auth_handler->request_url();
6551 EXPECT_EQ("https", request_url.scheme());
6552 EXPECT_EQ("www.google.com", request_url.host());
6553
6554 HttpNetworkTransaction::SetNextProtos("");
6555 HttpNetworkTransaction::SetUseAlternateProtocols(false);
6556}
6557
[email protected]89ceba9a2009-03-21 03:46:066558} // namespace net