blob: 68e40381a1cbd056f7206d8a3655673b79792135 [file] [log] [blame]
[email protected]95d88ffe2010-02-04 21:25:331// Copyright (c) 2010 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]6624b4622010-03-29 19:58:3614#include "base/scoped_ptr.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]db36938c2009-08-19 21:48:4223#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3324#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5225#include "net/base/test_completion_callback.h"
26#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1227#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0028#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2929#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5730#include "net/http/http_basic_stream.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/http/http_network_session.h"
[email protected]0877e3d2009-10-17 22:29:5732#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3833#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5234#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5335#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1136#include "net/proxy/proxy_resolver.h"
37#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4438#include "net/socket/client_socket_factory.h"
39#include "net/socket/socket_test_util.h"
40#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5441#include "net/spdy/spdy_framer.h"
42#include "net/spdy/spdy_session.h"
43#include "net/spdy/spdy_session_pool.h"
44#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5245#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1546#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5247
48//-----------------------------------------------------------------------------
49
[email protected]13c8a092010-07-29 06:15:4450namespace {
51
52const string16 kBar(ASCIIToUTF16("bar"));
53const string16 kBar2(ASCIIToUTF16("bar2"));
54const string16 kBar3(ASCIIToUTF16("bar3"));
55const string16 kBaz(ASCIIToUTF16("baz"));
56const string16 kFirst(ASCIIToUTF16("first"));
57const string16 kFoo(ASCIIToUTF16("foo"));
58const string16 kFoo2(ASCIIToUTF16("foo2"));
59const string16 kFoo3(ASCIIToUTF16("foo3"));
60const string16 kFou(ASCIIToUTF16("fou"));
61const string16 kSecond(ASCIIToUTF16("second"));
62const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
63const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
64
65} // namespace
66
[email protected]89ceba9a2009-03-21 03:46:0667namespace net {
68
[email protected]2d731a32010-04-29 01:04:0669class HttpNetworkSessionPeer {
70 public:
71 explicit HttpNetworkSessionPeer(
72 const scoped_refptr<HttpNetworkSession>& session)
73 : session_(session) {}
74
[email protected]2431756e2010-09-29 20:26:1375 void SetTCPSocketPool(TCPClientSocketPool* pool) {
76 session_->socket_pool_manager_.tcp_socket_pool_.reset(pool);
[email protected]2d731a32010-04-29 01:04:0677 }
78
79 void SetSocketPoolForSOCKSProxy(
80 const HostPortPair& socks_proxy,
[email protected]2431756e2010-09-29 20:26:1381 SOCKSClientSocketPool* pool) {
82 ClientSocketPoolManager* socket_pool_manager =
83 &session_->socket_pool_manager_;
84
85 // Call through the public interface to force initialization of the
86 // wrapped socket pools.
87 delete socket_pool_manager->GetSocketPoolForSOCKSProxy(socks_proxy);
88 socket_pool_manager->socks_socket_pools_[socks_proxy] = pool;
[email protected]2d731a32010-04-29 01:04:0689 }
90
91 void SetSocketPoolForHTTPProxy(
92 const HostPortPair& http_proxy,
[email protected]2431756e2010-09-29 20:26:1393 HttpProxyClientSocketPool* pool) {
94 ClientSocketPoolManager* socket_pool_manager =
95 &session_->socket_pool_manager_;
96
97 // Call through the public interface to force initialization of the
98 // wrapped socket pools.
99 delete socket_pool_manager->GetSocketPoolForHTTPProxy(http_proxy);
100 socket_pool_manager->http_proxy_socket_pools_[http_proxy] = pool;
[email protected]e60e47a2010-07-14 03:37:18101 }
102
[email protected]2431756e2010-09-29 20:26:13103 void SetSSLSocketPool(SSLClientSocketPool* pool) {
104 session_->socket_pool_manager_.ssl_socket_pool_.reset(pool);
[email protected]e60e47a2010-07-14 03:37:18105 }
106
107 void SetSocketPoolForSSLWithProxy(
108 const HostPortPair& proxy_host,
[email protected]2431756e2010-09-29 20:26:13109 SSLClientSocketPool* pool) {
110 ClientSocketPoolManager* socket_pool_manager =
111 &session_->socket_pool_manager_;
112
113 // Call through the public interface to force initialization of the
114 // wrapped socket pools.
115 delete socket_pool_manager->GetSocketPoolForSSLWithProxy(proxy_host);
116 socket_pool_manager->ssl_socket_pools_for_proxies_[proxy_host] = pool;
[email protected]2d731a32010-04-29 01:04:06117 }
118
119 private:
120 const scoped_refptr<HttpNetworkSession> session_;
121
122 DISALLOW_COPY_AND_ASSIGN(HttpNetworkSessionPeer);
123};
124
[email protected]e44de5d2009-06-05 20:12:45125// Helper to manage the lifetimes of the dependencies for a
126// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44127struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59128 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42129 SessionDependencies()
130 : host_resolver(new MockHostResolver),
[email protected]ebeefff32010-09-15 05:10:02131 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:10132 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08133 http_auth_handler_factory(
134 HttpAuthHandlerFactory::CreateDefault(host_resolver)),
[email protected]7abf7d22010-09-04 01:41:59135 spdy_session_pool(new SpdySessionPool(NULL)),
[email protected]a7ea8832010-07-12 17:54:54136 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59137
138 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45139 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42140 : host_resolver(new MockHostResolver),
141 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10142 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08143 http_auth_handler_factory(
144 HttpAuthHandlerFactory::CreateDefault(host_resolver)),
[email protected]7abf7d22010-09-04 01:41:59145 spdy_session_pool(new SpdySessionPool(NULL)),
[email protected]a7ea8832010-07-12 17:54:54146 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59147
[email protected]a2c2fb92009-07-18 07:31:04148 scoped_refptr<MockHostResolverBase> host_resolver;
[email protected]80d6524d2009-08-18 03:58:09149 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42150 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59151 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50152 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a554a8262010-05-20 00:13:52153 scoped_refptr<SpdySessionPool> spdy_session_pool;
[email protected]a7ea8832010-07-12 17:54:54154 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59155};
156
[email protected]1c773ea12009-04-28 19:58:42157ProxyService* CreateFixedProxyService(const std::string& proxy) {
[email protected]ab501a6a2009-05-12 15:07:50158 net::ProxyConfig proxy_config;
[email protected]ed4ed0f2010-02-24 00:20:48159 proxy_config.proxy_rules().ParseFromString(proxy);
[email protected]3e44697f2009-05-22 14:37:39160 return ProxyService::CreateFixed(proxy_config);
[email protected]51fff29d2008-12-19 22:17:53161}
162
[email protected]228ff742009-06-05 01:19:59163HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]66761b952010-06-25 21:30:38164 return new HttpNetworkSession(session_deps->host_resolver,
[email protected]80d6524d2009-08-18 03:58:09165 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42166 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10167 session_deps->ssl_config_service,
[email protected]a554a8262010-05-20 00:13:52168 session_deps->spdy_session_pool,
[email protected]06650c52010-06-03 00:49:17169 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44170 NULL,
[email protected]a7ea8832010-07-12 17:54:54171 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14172}
173
[email protected]89836e22008-09-25 20:33:42174class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52175 public:
[email protected]2ff8b312010-04-26 22:20:54176 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50177 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
178 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54179 spdy::SpdyFramer::set_enable_compression_default(false);
180 }
181
[email protected]0e75a732008-10-16 20:36:09182 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50183 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
184 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54185 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09186 // Empty the current queue.
187 MessageLoop::current()->RunAllPending();
188 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50189 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
190 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09191 }
192
[email protected]3d2a59b2008-09-26 19:44:25193 protected:
194 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52195
[email protected]ff007e162009-05-23 09:13:15196 struct SimpleGetHelperResult {
197 int rv;
198 std::string status_line;
199 std::string response_data;
200 };
initial.commit586acc5fe2008-07-26 22:42:52201
[email protected]31a2bfe2010-02-09 08:03:39202 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
203 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15204 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52205
[email protected]228ff742009-06-05 01:19:59206 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40207 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43208 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52209
[email protected]ff007e162009-05-23 09:13:15210 HttpRequestInfo request;
211 request.method = "GET";
212 request.url = GURL("http://www.google.com/");
213 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52214
[email protected]31a2bfe2010-02-09 08:03:39215 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59216 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52217
[email protected]ff007e162009-05-23 09:13:15218 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52219
[email protected]169d0012010-05-10 23:20:12220 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
221 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15222 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52223
[email protected]ff007e162009-05-23 09:13:15224 out.rv = callback.WaitForResult();
225 if (out.rv != OK)
226 return out;
227
228 const HttpResponseInfo* response = trans->GetResponseInfo();
229 EXPECT_TRUE(response != NULL);
230
231 EXPECT_TRUE(response->headers != NULL);
232 out.status_line = response->headers->GetStatusLine();
233
234 rv = ReadTransaction(trans.get(), &out.response_data);
235 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:39236 size_t pos = ExpectLogContainsSomewhere(
[email protected]169d0012010-05-10 23:20:12237 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
238 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39239 ExpectLogContainsSomewhere(
240 log.entries(), pos,
241 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
242 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15243
[email protected]aecfbf22008-10-16 02:02:47244 return out;
[email protected]ff007e162009-05-23 09:13:15245 }
initial.commit586acc5fe2008-07-26 22:42:52246
[email protected]ff007e162009-05-23 09:13:15247 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
248 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52249
[email protected]ff007e162009-05-23 09:13:15250 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15251};
[email protected]231d5a32008-09-13 00:45:27252
[email protected]15a5ccf82008-10-23 19:57:43253// Fill |str| with a long header list that consumes >= |size| bytes.
254void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19255 const char* row =
256 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
257 const int sizeof_row = strlen(row);
258 const int num_rows = static_cast<int>(
259 ceil(static_cast<float>(size) / sizeof_row));
260 const int sizeof_data = num_rows * sizeof_row;
261 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43262 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51263
[email protected]4ddaf2502008-10-23 18:26:19264 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43265 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19266}
267
[email protected]385a4672009-03-11 22:21:29268// Alternative functions that eliminate randomness and dependency on the local
269// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20270void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29271 static const uint8 bytes[] = {
272 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
273 };
274 static size_t current_byte = 0;
275 for (size_t i = 0; i < n; ++i) {
276 output[i] = bytes[current_byte++];
277 current_byte %= arraysize(bytes);
278 }
279}
280
[email protected]fe2bc6a2009-03-23 16:52:20281void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29282 static const uint8 bytes[] = {
283 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
284 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
285 };
286 static size_t current_byte = 0;
287 for (size_t i = 0; i < n; ++i) {
288 output[i] = bytes[current_byte++];
289 current_byte %= arraysize(bytes);
290 }
291}
292
[email protected]fe2bc6a2009-03-23 16:52:20293std::string MockGetHostName() {
294 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29295}
296
[email protected]e60e47a2010-07-14 03:37:18297template<typename ParentPool>
298class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31299 public:
[email protected]e60e47a2010-07-14 03:37:18300 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
301
[email protected]d80a4322009-08-14 07:07:49302 const std::string last_group_name_received() const {
303 return last_group_name_;
304 }
305
[email protected]684970b2009-08-14 04:54:46306 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49307 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31308 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31309 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46310 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53311 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31312 last_group_name_ = group_name;
313 return ERR_IO_PENDING;
314 }
[email protected]04e5be32009-06-26 20:00:31315 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21316 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31317 virtual void ReleaseSocket(const std::string& group_name,
318 ClientSocket* socket) {}
319 virtual void CloseIdleSockets() {}
320 virtual HostResolver* GetHostResolver() const {
321 return NULL;
322 }
323 virtual int IdleSocketCount() const {
324 return 0;
325 }
326 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
327 return 0;
328 }
329 virtual LoadState GetLoadState(const std::string& group_name,
330 const ClientSocketHandle* handle) const {
331 return LOAD_STATE_IDLE;
332 }
[email protected]a796bcec2010-03-22 17:17:26333 virtual base::TimeDelta ConnectionTimeout() const {
334 return base::TimeDelta();
335 }
[email protected]d80a4322009-08-14 07:07:49336
337 private:
[email protected]04e5be32009-06-26 20:00:31338 std::string last_group_name_;
339};
340
[email protected]2d731a32010-04-29 01:04:06341typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11342CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13343typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
344CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06345typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11346CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18347typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
348CaptureGroupNameSSLSocketPool;
349
350template<typename ParentPool>
351CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
352 HttpNetworkSession* session)
353 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
354
355template<>
[email protected]2df19bb2010-08-25 20:13:46356CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
357 HttpNetworkSession* session)
358 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
359 NULL, NULL) {}
360
361template<>
[email protected]e60e47a2010-07-14 03:37:18362CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
363 HttpNetworkSession* session)
364 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(), NULL, NULL,
[email protected]7abf7d22010-09-04 01:41:59365 NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11366
[email protected]231d5a32008-09-13 00:45:27367//-----------------------------------------------------------------------------
368
[email protected]dae22c52010-07-30 02:16:35369// This is the expected list of advertised protocols from the browser's NPN
370// list.
371static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
372
373// This is the expected return from a current server advertising SPDY.
374static const char kAlternateProtocolHttpHeader[] =
375 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
376
[email protected]231d5a32008-09-13 00:45:27377TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59378 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40379 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43380 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27381}
382
383TEST_F(HttpNetworkTransactionTest, SimpleGET) {
384 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35385 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
386 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42387 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27388 };
[email protected]31a2bfe2010-02-09 08:03:39389 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
390 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42391 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27392 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
393 EXPECT_EQ("hello world", out.response_data);
394}
395
396// Response with no status line.
397TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
398 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35399 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42400 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27401 };
[email protected]31a2bfe2010-02-09 08:03:39402 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
403 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42404 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27405 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
406 EXPECT_EQ("hello world", out.response_data);
407}
408
409// Allow up to 4 bytes of junk to precede status line.
410TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
411 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35412 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42413 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27414 };
[email protected]31a2bfe2010-02-09 08:03:39415 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
416 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42417 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27418 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
419 EXPECT_EQ("DATA", out.response_data);
420}
421
422// Allow up to 4 bytes of junk to precede status line.
423TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
424 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35425 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42426 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27427 };
[email protected]31a2bfe2010-02-09 08:03:39428 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
429 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42430 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27431 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
432 EXPECT_EQ("DATA", out.response_data);
433}
434
435// Beyond 4 bytes of slop and it should fail to find a status line.
436TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
437 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35438 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42439 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27440 };
[email protected]31a2bfe2010-02-09 08:03:39441 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
442 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42443 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25444 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
445 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27446}
447
448// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
449TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
450 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35451 MockRead("\n"),
452 MockRead("\n"),
453 MockRead("Q"),
454 MockRead("J"),
455 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42456 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27457 };
[email protected]31a2bfe2010-02-09 08:03:39458 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
459 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42460 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27461 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
462 EXPECT_EQ("DATA", out.response_data);
463}
464
465// Close the connection before enough bytes to have a status line.
466TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
467 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35468 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42469 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27470 };
[email protected]31a2bfe2010-02-09 08:03:39471 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
472 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42473 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27474 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
475 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52476}
477
[email protected]f9d44aa2008-09-23 23:57:17478// Simulate a 204 response, lacking a Content-Length header, sent over a
479// persistent connection. The response should still terminate since a 204
480// cannot have a response body.
481TEST_F(HttpNetworkTransactionTest, StopsReading204) {
482 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35483 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
484 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42485 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17486 };
[email protected]31a2bfe2010-02-09 08:03:39487 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
488 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42489 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17490 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
491 EXPECT_EQ("", out.response_data);
492}
493
[email protected]0877e3d2009-10-17 22:29:57494// A simple request using chunked encoding with some extra data after.
495// (Like might be seen in a pipelined response.)
496TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
497 MockRead data_reads[] = {
498 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
499 MockRead("5\r\nHello\r\n"),
500 MockRead("1\r\n"),
501 MockRead(" \r\n"),
502 MockRead("5\r\nworld\r\n"),
503 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
504 MockRead(false, OK),
505 };
[email protected]31a2bfe2010-02-09 08:03:39506 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
507 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57508 EXPECT_EQ(OK, out.rv);
509 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
510 EXPECT_EQ("Hello world", out.response_data);
511}
512
[email protected]9fe44f52010-09-23 18:36:00513// Next tests deal with http://crbug.com/56344.
514
515TEST_F(HttpNetworkTransactionTest,
516 MultipleContentLengthHeadersNoTransferEncoding) {
517 MockRead data_reads[] = {
518 MockRead("HTTP/1.1 200 OK\r\n"),
519 MockRead("Content-Length: 10\r\n"),
520 MockRead("Content-Length: 5\r\n\r\n"),
521 };
522 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
523 arraysize(data_reads));
524 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
525}
526
527TEST_F(HttpNetworkTransactionTest,
528 MultipleContentLengthHeadersTransferEncoding) {
529 MockRead data_reads[] = {
530 MockRead("HTTP/1.1 200 OK\r\n"),
531 MockRead("Content-Length: 666\r\n"),
532 MockRead("Content-Length: 1337\r\n"),
533 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
534 MockRead("5\r\nHello\r\n"),
535 MockRead("1\r\n"),
536 MockRead(" \r\n"),
537 MockRead("5\r\nworld\r\n"),
538 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
539 MockRead(false, OK),
540 };
541 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
542 arraysize(data_reads));
543 EXPECT_EQ(OK, out.rv);
544 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
545 EXPECT_EQ("Hello world", out.response_data);
546}
547
[email protected]ef0faf2e72009-03-05 23:27:23548// Do a request using the HEAD method. Verify that we don't try to read the
549// message body (since HEAD has none).
550TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59551 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40552 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43553 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23554
[email protected]1c773ea12009-04-28 19:58:42555 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23556 request.method = "HEAD";
557 request.url = GURL("http://www.google.com/");
558 request.load_flags = 0;
559
560 MockWrite data_writes1[] = {
561 MockWrite("HEAD / HTTP/1.1\r\n"
562 "Host: www.google.com\r\n"
563 "Connection: keep-alive\r\n"
564 "Content-Length: 0\r\n\r\n"),
565 };
566 MockRead data_reads1[] = {
567 MockRead("HTTP/1.1 404 Not Found\r\n"),
568 MockRead("Server: Blah\r\n"),
569 MockRead("Content-Length: 1234\r\n\r\n"),
570
571 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42572 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23573 };
574
[email protected]31a2bfe2010-02-09 08:03:39575 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
576 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59577 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23578
579 TestCompletionCallback callback1;
580
[email protected]5a1d7ca2010-04-28 20:12:27581 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42582 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23583
584 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42585 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23586
[email protected]1c773ea12009-04-28 19:58:42587 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23588 EXPECT_FALSE(response == NULL);
589
590 // Check that the headers got parsed.
591 EXPECT_TRUE(response->headers != NULL);
592 EXPECT_EQ(1234, response->headers->GetContentLength());
593 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
594
595 std::string server_header;
596 void* iter = NULL;
597 bool has_server_header = response->headers->EnumerateHeader(
598 &iter, "Server", &server_header);
599 EXPECT_TRUE(has_server_header);
600 EXPECT_EQ("Blah", server_header);
601
602 // Reading should give EOF right away, since there is no message body
603 // (despite non-zero content-length).
604 std::string response_data;
605 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42606 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23607 EXPECT_EQ("", response_data);
608}
609
initial.commit586acc5fe2008-07-26 22:42:52610TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59611 SessionDependencies session_deps;
612 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52613
614 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35615 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
616 MockRead("hello"),
617 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
618 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42619 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52620 };
[email protected]31a2bfe2010-02-09 08:03:39621 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59622 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52623
[email protected]0b0bf032010-09-21 18:08:50624 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52625 "hello", "world"
626 };
627
628 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43629 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52630
[email protected]1c773ea12009-04-28 19:58:42631 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52632 request.method = "GET";
633 request.url = GURL("http://www.google.com/");
634 request.load_flags = 0;
635
636 TestCompletionCallback callback;
637
[email protected]5a1d7ca2010-04-28 20:12:27638 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42639 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52640
641 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42642 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52643
[email protected]1c773ea12009-04-28 19:58:42644 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52645 EXPECT_TRUE(response != NULL);
646
647 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25648 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52649
650 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57651 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42652 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25653 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52654 }
655}
656
657TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59658 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40659 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43660 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52661
[email protected]1c773ea12009-04-28 19:58:42662 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52663 request.method = "POST";
664 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42665 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52666 request.upload_data->AppendBytes("foo", 3);
667 request.load_flags = 0;
668
669 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35670 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
671 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
672 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42673 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52674 };
[email protected]31a2bfe2010-02-09 08:03:39675 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59676 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52677
678 TestCompletionCallback callback;
679
[email protected]5a1d7ca2010-04-28 20:12:27680 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42681 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52682
683 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42684 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52685
[email protected]1c773ea12009-04-28 19:58:42686 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52687 EXPECT_TRUE(response != NULL);
688
689 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25690 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52691
692 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57693 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42694 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25695 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52696}
697
[email protected]3a2d3662009-03-27 03:49:14698// This test is almost the same as Ignores100 above, but the response contains
699// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57700// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14701TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59702 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40703 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43704 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14705
[email protected]1c773ea12009-04-28 19:58:42706 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14707 request.method = "GET";
708 request.url = GURL("http://www.foo.com/");
709 request.load_flags = 0;
710
711 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57712 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
713 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14714 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42715 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14716 };
[email protected]31a2bfe2010-02-09 08:03:39717 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59718 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14719
720 TestCompletionCallback callback;
721
[email protected]5a1d7ca2010-04-28 20:12:27722 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42723 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14724
725 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42726 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14727
[email protected]1c773ea12009-04-28 19:58:42728 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14729 EXPECT_TRUE(response != NULL);
730
731 EXPECT_TRUE(response->headers != NULL);
732 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
733
734 std::string response_data;
735 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42736 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14737 EXPECT_EQ("hello world", response_data);
738}
739
[email protected]ee9410e72010-01-07 01:42:38740TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
741 SessionDependencies session_deps;
742 scoped_ptr<HttpTransaction> trans(
743 new HttpNetworkTransaction(CreateSession(&session_deps)));
744
745 HttpRequestInfo request;
746 request.method = "POST";
747 request.url = GURL("http://www.foo.com/");
748 request.load_flags = 0;
749
750 MockRead data_reads[] = {
751 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
752 MockRead(true, 0),
753 };
[email protected]31a2bfe2010-02-09 08:03:39754 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38755 session_deps.socket_factory.AddSocketDataProvider(&data);
756
757 TestCompletionCallback callback;
758
[email protected]5a1d7ca2010-04-28 20:12:27759 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38760 EXPECT_EQ(ERR_IO_PENDING, rv);
761
762 rv = callback.WaitForResult();
763 EXPECT_EQ(OK, rv);
764
765 std::string response_data;
766 rv = ReadTransaction(trans.get(), &response_data);
767 EXPECT_EQ(OK, rv);
768 EXPECT_EQ("", response_data);
769}
770
771TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
772 SessionDependencies session_deps;
773 scoped_ptr<HttpTransaction> trans(
774 new HttpNetworkTransaction(CreateSession(&session_deps)));
775
776 HttpRequestInfo request;
777 request.method = "POST";
778 request.url = GURL("http://www.foo.com/");
779 request.load_flags = 0;
780
781 MockRead data_reads[] = {
782 MockRead(true, 0),
783 };
[email protected]31a2bfe2010-02-09 08:03:39784 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38785 session_deps.socket_factory.AddSocketDataProvider(&data);
786
787 TestCompletionCallback callback;
788
[email protected]5a1d7ca2010-04-28 20:12:27789 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38790 EXPECT_EQ(ERR_IO_PENDING, rv);
791
792 rv = callback.WaitForResult();
793 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
794}
795
[email protected]3d2a59b2008-09-26 19:44:25796// read_failure specifies a read failure that should cause the network
797// transaction to resend the request.
798void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
799 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59800 SessionDependencies session_deps;
801 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
initial.commit586acc5fe2008-07-26 22:42:52802
[email protected]1c773ea12009-04-28 19:58:42803 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52804 request.method = "GET";
805 request.url = GURL("http://www.foo.com/");
806 request.load_flags = 0;
807
808 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35809 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
810 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25811 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52812 };
[email protected]31a2bfe2010-02-09 08:03:39813 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59814 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52815
816 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35817 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
818 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42819 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52820 };
[email protected]31a2bfe2010-02-09 08:03:39821 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59822 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52823
824 const char* kExpectedResponseData[] = {
825 "hello", "world"
826 };
827
828 for (int i = 0; i < 2; ++i) {
829 TestCompletionCallback callback;
830
[email protected]5695b8c2009-09-30 21:36:43831 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52832
[email protected]5a1d7ca2010-04-28 20:12:27833 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42834 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52835
836 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42837 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52838
[email protected]1c773ea12009-04-28 19:58:42839 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52840 EXPECT_TRUE(response != NULL);
841
842 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25843 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52844
845 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57846 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42847 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25848 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52849 }
850}
[email protected]3d2a59b2008-09-26 19:44:25851
852TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42853 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25854 KeepAliveConnectionResendRequestTest(read_failure);
855}
856
857TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42858 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25859 KeepAliveConnectionResendRequestTest(read_failure);
860}
861
862TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59863 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40864 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43865 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25866
[email protected]1c773ea12009-04-28 19:58:42867 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25868 request.method = "GET";
869 request.url = GURL("http://www.google.com/");
870 request.load_flags = 0;
871
872 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42873 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35874 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
875 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42876 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25877 };
[email protected]31a2bfe2010-02-09 08:03:39878 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59879 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25880
881 TestCompletionCallback callback;
882
[email protected]5a1d7ca2010-04-28 20:12:27883 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42884 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25885
886 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42887 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25888
[email protected]1c773ea12009-04-28 19:58:42889 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25890 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25891}
892
893// What do various browsers do when the server closes a non-keepalive
894// connection without sending any response header or body?
895//
896// IE7: error page
897// Safari 3.1.2 (Windows): error page
898// Firefox 3.0.1: blank page
899// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42900// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
901// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25902TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
903 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42904 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35905 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
906 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42907 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25908 };
[email protected]31a2bfe2010-02-09 08:03:39909 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
910 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42911 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25912}
[email protected]038e9a32008-10-08 22:40:16913
[email protected]0b0bf032010-09-21 18:08:50914// Test that we correctly reuse a keep-alive connection after not explicitly
915// reading the body.
916TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13917 SessionDependencies session_deps;
918 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
919
920 HttpRequestInfo request;
921 request.method = "GET";
922 request.url = GURL("http://www.foo.com/");
923 request.load_flags = 0;
924
[email protected]0b0bf032010-09-21 18:08:50925 // Note that because all these reads happen in the same
926 // StaticSocketDataProvider, it shows that the same socket is being reused for
927 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13928 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50929 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
930 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13931 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50932 MockRead("HTTP/1.1 302 Found\r\n"
933 "Content-Length: 0\r\n\r\n"),
934 MockRead("HTTP/1.1 302 Found\r\n"
935 "Content-Length: 5\r\n\r\n"
936 "hello"),
937 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
938 "Content-Length: 0\r\n\r\n"),
939 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
940 "Content-Length: 5\r\n\r\n"
941 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13942 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
943 MockRead("hello"),
944 };
945 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
946 session_deps.socket_factory.AddSocketDataProvider(&data1);
947
948 MockRead data2_reads[] = {
949 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
950 };
951 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
952 session_deps.socket_factory.AddSocketDataProvider(&data2);
953
[email protected]0b0bf032010-09-21 18:08:50954 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
955 std::string response_lines[kNumUnreadBodies];
956
957 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13958 TestCompletionCallback callback;
959
960 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
961
962 int rv = trans->Start(&request, &callback, BoundNetLog());
963 EXPECT_EQ(ERR_IO_PENDING, rv);
964
965 rv = callback.WaitForResult();
966 EXPECT_EQ(OK, rv);
967
968 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50969 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13970
[email protected]0b0bf032010-09-21 18:08:50971 ASSERT_TRUE(response->headers != NULL);
972 response_lines[i] = response->headers->GetStatusLine();
973
974 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13975 }
[email protected]0b0bf032010-09-21 18:08:50976
977 const char* const kStatusLines[] = {
978 "HTTP/1.1 204 No Content",
979 "HTTP/1.1 205 Reset Content",
980 "HTTP/1.1 304 Not Modified",
981 "HTTP/1.1 302 Found",
982 "HTTP/1.1 302 Found",
983 "HTTP/1.1 301 Moved Permanently",
984 "HTTP/1.1 301 Moved Permanently",
985 };
986
987 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
988 forgot_to_update_kStatusLines);
989
990 for (int i = 0; i < kNumUnreadBodies; ++i)
991 EXPECT_EQ(kStatusLines[i], response_lines[i]);
992
993 TestCompletionCallback callback;
994 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
995 int rv = trans->Start(&request, &callback, BoundNetLog());
996 EXPECT_EQ(ERR_IO_PENDING, rv);
997 rv = callback.WaitForResult();
998 EXPECT_EQ(OK, rv);
999 const HttpResponseInfo* response = trans->GetResponseInfo();
1000 ASSERT_TRUE(response != NULL);
1001 ASSERT_TRUE(response->headers != NULL);
1002 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1003 std::string response_data;
1004 rv = ReadTransaction(trans.get(), &response_data);
1005 EXPECT_EQ(OK, rv);
1006 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131007}
1008
[email protected]038e9a32008-10-08 22:40:161009// Test the request-challenge-retry sequence for basic auth.
1010// (basic auth is the easiest to mock, because it has no randomness).
1011TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:591012 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401013 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431014 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161015
[email protected]1c773ea12009-04-28 19:58:421016 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161017 request.method = "GET";
1018 request.url = GURL("http://www.google.com/");
1019 request.load_flags = 0;
1020
[email protected]f9ee6b52008-11-08 06:46:231021 MockWrite data_writes1[] = {
1022 MockWrite("GET / HTTP/1.1\r\n"
1023 "Host: www.google.com\r\n"
1024 "Connection: keep-alive\r\n\r\n"),
1025 };
1026
[email protected]038e9a32008-10-08 22:40:161027 MockRead data_reads1[] = {
1028 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1029 // Give a couple authenticate options (only the middle one is actually
1030 // supported).
[email protected]22927ad2009-09-21 19:56:191031 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161032 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1033 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1034 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1035 // Large content-length -- won't matter, as connection will be reset.
1036 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421037 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161038 };
1039
1040 // After calling trans->RestartWithAuth(), this is the request we should
1041 // be issuing -- the final header line contains the credentials.
1042 MockWrite data_writes2[] = {
1043 MockWrite("GET / HTTP/1.1\r\n"
1044 "Host: www.google.com\r\n"
1045 "Connection: keep-alive\r\n"
1046 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1047 };
1048
1049 // Lastly, the server responds with the actual content.
1050 MockRead data_reads2[] = {
1051 MockRead("HTTP/1.0 200 OK\r\n"),
1052 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1053 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421054 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161055 };
1056
[email protected]31a2bfe2010-02-09 08:03:391057 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1058 data_writes1, arraysize(data_writes1));
1059 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1060 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591061 session_deps.socket_factory.AddSocketDataProvider(&data1);
1062 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161063
1064 TestCompletionCallback callback1;
1065
[email protected]5a1d7ca2010-04-28 20:12:271066 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421067 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161068
1069 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421070 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161071
[email protected]1c773ea12009-04-28 19:58:421072 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161073 EXPECT_FALSE(response == NULL);
1074
1075 // The password prompt info should have been set in response->auth_challenge.
1076 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1077
[email protected]71e4573a2009-05-21 22:03:001078 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161079 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1080 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1081
1082 TestCompletionCallback callback2;
1083
[email protected]13c8a092010-07-29 06:15:441084 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421085 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161086
1087 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421088 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161089
1090 response = trans->GetResponseInfo();
1091 EXPECT_FALSE(response == NULL);
1092 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1093 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161094}
1095
[email protected]861fcd52009-08-26 02:33:461096TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1097 SessionDependencies session_deps;
1098 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431099 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:461100
1101 HttpRequestInfo request;
1102 request.method = "GET";
1103 request.url = GURL("http://www.google.com/");
1104 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1105
1106 MockWrite data_writes[] = {
1107 MockWrite("GET / HTTP/1.1\r\n"
1108 "Host: www.google.com\r\n"
1109 "Connection: keep-alive\r\n\r\n"),
1110 };
1111
1112 MockRead data_reads[] = {
1113 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1114 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1115 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1116 // Large content-length -- won't matter, as connection will be reset.
1117 MockRead("Content-Length: 10000\r\n\r\n"),
1118 MockRead(false, ERR_FAILED),
1119 };
1120
[email protected]31a2bfe2010-02-09 08:03:391121 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1122 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591123 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461124 TestCompletionCallback callback;
1125
[email protected]5a1d7ca2010-04-28 20:12:271126 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461127 EXPECT_EQ(ERR_IO_PENDING, rv);
1128
1129 rv = callback.WaitForResult();
1130 EXPECT_EQ(0, rv);
1131
1132 const HttpResponseInfo* response = trans->GetResponseInfo();
1133 ASSERT_FALSE(response == NULL);
1134 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1135}
1136
[email protected]2d2697f92009-02-18 21:00:321137// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1138// connection.
1139TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591140 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501141 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321142
[email protected]1c773ea12009-04-28 19:58:421143 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321144 request.method = "GET";
1145 request.url = GURL("http://www.google.com/");
1146 request.load_flags = 0;
1147
1148 MockWrite data_writes1[] = {
1149 MockWrite("GET / HTTP/1.1\r\n"
1150 "Host: www.google.com\r\n"
1151 "Connection: keep-alive\r\n\r\n"),
1152
1153 // After calling trans->RestartWithAuth(), this is the request we should
1154 // be issuing -- the final header line contains the credentials.
1155 MockWrite("GET / HTTP/1.1\r\n"
1156 "Host: www.google.com\r\n"
1157 "Connection: keep-alive\r\n"
1158 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1159 };
1160
1161 MockRead data_reads1[] = {
1162 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1163 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1164 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1165 MockRead("Content-Length: 14\r\n\r\n"),
1166 MockRead("Unauthorized\r\n"),
1167
1168 // Lastly, the server responds with the actual content.
1169 MockRead("HTTP/1.1 200 OK\r\n"),
1170 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501171 MockRead("Content-Length: 5\r\n\r\n"),
1172 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321173 };
1174
[email protected]31a2bfe2010-02-09 08:03:391175 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1176 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591177 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321178
1179 TestCompletionCallback callback1;
1180
[email protected]0b0bf032010-09-21 18:08:501181 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271182 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421183 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321184
1185 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421186 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321187
[email protected]1c773ea12009-04-28 19:58:421188 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321189 EXPECT_FALSE(response == NULL);
1190
1191 // The password prompt info should have been set in response->auth_challenge.
1192 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1193
[email protected]71e4573a2009-05-21 22:03:001194 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321195 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1196 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1197
1198 TestCompletionCallback callback2;
1199
[email protected]13c8a092010-07-29 06:15:441200 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421201 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321202
1203 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421204 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321205
1206 response = trans->GetResponseInfo();
1207 EXPECT_FALSE(response == NULL);
1208 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501209 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321210}
1211
1212// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1213// connection and with no response body to drain.
1214TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591215 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501216 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321217
[email protected]1c773ea12009-04-28 19:58:421218 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321219 request.method = "GET";
1220 request.url = GURL("http://www.google.com/");
1221 request.load_flags = 0;
1222
1223 MockWrite data_writes1[] = {
1224 MockWrite("GET / HTTP/1.1\r\n"
1225 "Host: www.google.com\r\n"
1226 "Connection: keep-alive\r\n\r\n"),
1227
1228 // After calling trans->RestartWithAuth(), this is the request we should
1229 // be issuing -- the final header line contains the credentials.
1230 MockWrite("GET / HTTP/1.1\r\n"
1231 "Host: www.google.com\r\n"
1232 "Connection: keep-alive\r\n"
1233 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1234 };
1235
[email protected]2d2697f92009-02-18 21:00:321236 MockRead data_reads1[] = {
1237 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1238 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311239 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321240
1241 // Lastly, the server responds with the actual content.
1242 MockRead("HTTP/1.1 200 OK\r\n"),
1243 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501244 MockRead("Content-Length: 5\r\n\r\n"),
1245 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321246 };
1247
[email protected]31a2bfe2010-02-09 08:03:391248 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1249 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591250 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321251
1252 TestCompletionCallback callback1;
1253
[email protected]0b0bf032010-09-21 18:08:501254 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271255 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421256 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321257
1258 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421259 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321260
[email protected]1c773ea12009-04-28 19:58:421261 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321262 EXPECT_FALSE(response == NULL);
1263
1264 // The password prompt info should have been set in response->auth_challenge.
1265 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1266
[email protected]71e4573a2009-05-21 22:03:001267 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321268 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1269 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1270
1271 TestCompletionCallback callback2;
1272
[email protected]13c8a092010-07-29 06:15:441273 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421274 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321275
1276 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421277 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321278
1279 response = trans->GetResponseInfo();
1280 EXPECT_FALSE(response == NULL);
1281 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501282 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321283}
1284
1285// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1286// connection and with a large response body to drain.
1287TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591288 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501289 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321290
[email protected]1c773ea12009-04-28 19:58:421291 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321292 request.method = "GET";
1293 request.url = GURL("http://www.google.com/");
1294 request.load_flags = 0;
1295
1296 MockWrite data_writes1[] = {
1297 MockWrite("GET / HTTP/1.1\r\n"
1298 "Host: www.google.com\r\n"
1299 "Connection: keep-alive\r\n\r\n"),
1300
1301 // After calling trans->RestartWithAuth(), this is the request we should
1302 // be issuing -- the final header line contains the credentials.
1303 MockWrite("GET / HTTP/1.1\r\n"
1304 "Host: www.google.com\r\n"
1305 "Connection: keep-alive\r\n"
1306 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1307 };
1308
1309 // Respond with 5 kb of response body.
1310 std::string large_body_string("Unauthorized");
1311 large_body_string.append(5 * 1024, ' ');
1312 large_body_string.append("\r\n");
1313
1314 MockRead data_reads1[] = {
1315 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1316 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1317 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1318 // 5134 = 12 + 5 * 1024 + 2
1319 MockRead("Content-Length: 5134\r\n\r\n"),
1320 MockRead(true, large_body_string.data(), large_body_string.size()),
1321
1322 // Lastly, the server responds with the actual content.
1323 MockRead("HTTP/1.1 200 OK\r\n"),
1324 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501325 MockRead("Content-Length: 5\r\n\r\n"),
1326 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321327 };
1328
[email protected]31a2bfe2010-02-09 08:03:391329 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1330 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591331 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321332
1333 TestCompletionCallback callback1;
1334
[email protected]0b0bf032010-09-21 18:08:501335 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271336 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421337 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321338
1339 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421340 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321341
[email protected]1c773ea12009-04-28 19:58:421342 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321343 EXPECT_FALSE(response == NULL);
1344
1345 // The password prompt info should have been set in response->auth_challenge.
1346 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1347
[email protected]71e4573a2009-05-21 22:03:001348 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321349 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1350 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1351
1352 TestCompletionCallback callback2;
1353
[email protected]13c8a092010-07-29 06:15:441354 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421355 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321356
1357 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421358 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321359
1360 response = trans->GetResponseInfo();
1361 EXPECT_FALSE(response == NULL);
1362 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501363 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321364}
1365
1366// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311367// connection, but the server gets impatient and closes the connection.
1368TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1369 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501370 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]11203f012009-11-12 23:02:311371
1372 HttpRequestInfo request;
1373 request.method = "GET";
1374 request.url = GURL("http://www.google.com/");
1375 request.load_flags = 0;
1376
1377 MockWrite data_writes1[] = {
1378 MockWrite("GET / HTTP/1.1\r\n"
1379 "Host: www.google.com\r\n"
1380 "Connection: keep-alive\r\n\r\n"),
1381 // This simulates the seemingly successful write to a closed connection
1382 // if the bug is not fixed.
1383 MockWrite("GET / HTTP/1.1\r\n"
1384 "Host: www.google.com\r\n"
1385 "Connection: keep-alive\r\n"
1386 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1387 };
1388
1389 MockRead data_reads1[] = {
1390 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1391 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1392 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1393 MockRead("Content-Length: 14\r\n\r\n"),
1394 // Tell MockTCPClientSocket to simulate the server closing the connection.
1395 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1396 MockRead("Unauthorized\r\n"),
1397 MockRead(false, OK), // The server closes the connection.
1398 };
1399
1400 // After calling trans->RestartWithAuth(), this is the request we should
1401 // be issuing -- the final header line contains the credentials.
1402 MockWrite data_writes2[] = {
1403 MockWrite("GET / HTTP/1.1\r\n"
1404 "Host: www.google.com\r\n"
1405 "Connection: keep-alive\r\n"
1406 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1407 };
1408
1409 // Lastly, the server responds with the actual content.
1410 MockRead data_reads2[] = {
1411 MockRead("HTTP/1.1 200 OK\r\n"),
1412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501413 MockRead("Content-Length: 5\r\n\r\n"),
1414 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311415 };
1416
[email protected]31a2bfe2010-02-09 08:03:391417 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1418 data_writes1, arraysize(data_writes1));
1419 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1420 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311421 session_deps.socket_factory.AddSocketDataProvider(&data1);
1422 session_deps.socket_factory.AddSocketDataProvider(&data2);
1423
1424 TestCompletionCallback callback1;
1425
[email protected]0b0bf032010-09-21 18:08:501426 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271427 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311428 EXPECT_EQ(ERR_IO_PENDING, rv);
1429
1430 rv = callback1.WaitForResult();
1431 EXPECT_EQ(OK, rv);
1432
1433 const HttpResponseInfo* response = trans->GetResponseInfo();
1434 EXPECT_FALSE(response == NULL);
1435
1436 // The password prompt info should have been set in response->auth_challenge.
1437 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1438
1439 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1440 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1441 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1442
1443 TestCompletionCallback callback2;
1444
[email protected]13c8a092010-07-29 06:15:441445 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311446 EXPECT_EQ(ERR_IO_PENDING, rv);
1447
1448 rv = callback2.WaitForResult();
1449 EXPECT_EQ(OK, rv);
1450
1451 response = trans->GetResponseInfo();
1452 ASSERT_FALSE(response == NULL);
1453 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501454 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311455}
1456
[email protected]394816e92010-08-03 07:38:591457// Test the request-challenge-retry sequence for basic auth, over a connection
1458// that requires a restart when setting up an SSL tunnel.
1459TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1460 // Configure against proxy server "myproxy:70".
1461 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
1462 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1463 session_deps.net_log = log.bound().net_log();
1464 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1465
[email protected]394816e92010-08-03 07:38:591466 HttpRequestInfo request;
1467 request.method = "GET";
1468 request.url = GURL("https://www.google.com/");
1469 // when the no authentication data flag is set.
1470 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1471
1472 // Since we have proxy, should try to establish tunnel.
1473 MockWrite data_writes1[] = {
1474 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1475 "Host: www.google.com\r\n"
1476 "Proxy-Connection: keep-alive\r\n\r\n"),
1477
1478 // After calling trans->RestartWithAuth(), this is the request we should
1479 // be issuing -- the final header line contains the credentials.
1480 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1481 "Host: www.google.com\r\n"
1482 "Proxy-Connection: keep-alive\r\n"
1483 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1484
1485 MockWrite("GET / HTTP/1.1\r\n"
1486 "Host: www.google.com\r\n"
1487 "Connection: keep-alive\r\n\r\n"),
1488 };
1489
1490 // The proxy responds to the connect with a 407, using a persistent
1491 // connection.
1492 MockRead data_reads1[] = {
1493 // No credentials.
1494 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1495 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1496 MockRead("Proxy-Connection: close\r\n\r\n"),
1497
1498 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1499
1500 MockRead("HTTP/1.1 200 OK\r\n"),
1501 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501502 MockRead("Content-Length: 5\r\n\r\n"),
1503 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591504 };
1505
1506 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1507 data_writes1, arraysize(data_writes1));
1508 session_deps.socket_factory.AddSocketDataProvider(&data1);
1509 SSLSocketDataProvider ssl(true, OK);
1510 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1511
1512 TestCompletionCallback callback1;
1513
[email protected]0b0bf032010-09-21 18:08:501514 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1515
[email protected]394816e92010-08-03 07:38:591516 int rv = trans->Start(&request, &callback1, log.bound());
1517 EXPECT_EQ(ERR_IO_PENDING, rv);
1518
1519 rv = callback1.WaitForResult();
1520 EXPECT_EQ(OK, rv);
1521 size_t pos = ExpectLogContainsSomewhere(
1522 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1523 NetLog::PHASE_NONE);
1524 ExpectLogContainsSomewhere(
1525 log.entries(), pos,
1526 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1527 NetLog::PHASE_NONE);
1528
1529 const HttpResponseInfo* response = trans->GetResponseInfo();
1530 ASSERT_FALSE(response == NULL);
1531
1532 EXPECT_EQ(407, response->headers->response_code());
1533 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1534
1535 // The password prompt info should have been set in response->auth_challenge.
1536 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1537
1538 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1539 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1540 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1541
1542 TestCompletionCallback callback2;
1543
1544 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1545 EXPECT_EQ(ERR_IO_PENDING, rv);
1546
1547 rv = callback2.WaitForResult();
1548 EXPECT_EQ(OK, rv);
1549
1550 response = trans->GetResponseInfo();
1551 ASSERT_FALSE(response == NULL);
1552
1553 EXPECT_TRUE(response->headers->IsKeepAlive());
1554 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501555 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591556 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1557
1558 // The password prompt info should not be set.
1559 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501560
1561 trans.reset();
1562 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591563}
1564
[email protected]11203f012009-11-12 23:02:311565// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321566// proxy connection, when setting up an SSL tunnel.
1567TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1568 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591569 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541570 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1571 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591572 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321573
[email protected]5695b8c2009-09-30 21:36:431574 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321575
[email protected]1c773ea12009-04-28 19:58:421576 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321577 request.method = "GET";
1578 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461579 // Ensure that proxy authentication is attempted even
1580 // when the no authentication data flag is set.
1581 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321582
1583 // Since we have proxy, should try to establish tunnel.
1584 MockWrite data_writes1[] = {
1585 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451586 "Host: www.google.com\r\n"
1587 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321588
1589 // After calling trans->RestartWithAuth(), this is the request we should
1590 // be issuing -- the final header line contains the credentials.
1591 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1592 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451593 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321594 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1595 };
1596
1597 // The proxy responds to the connect with a 407, using a persistent
1598 // connection.
1599 MockRead data_reads1[] = {
1600 // No credentials.
1601 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1602 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1603 MockRead("Content-Length: 10\r\n\r\n"),
1604 MockRead("0123456789"),
1605
1606 // Wrong credentials (wrong password).
1607 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1608 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1609 MockRead("Content-Length: 10\r\n\r\n"),
1610 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421611 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321612 };
1613
[email protected]31a2bfe2010-02-09 08:03:391614 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1615 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591616 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321617
1618 TestCompletionCallback callback1;
1619
[email protected]dbb83db2010-05-11 18:13:391620 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421621 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321622
1623 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421624 EXPECT_EQ(OK, rv);
[email protected]dbb83db2010-05-11 18:13:391625 size_t pos = ExpectLogContainsSomewhere(
1626 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
1627 NetLog::PHASE_NONE);
1628 ExpectLogContainsSomewhere(
1629 log.entries(), pos,
1630 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1631 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321632
[email protected]1c773ea12009-04-28 19:58:421633 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321634 EXPECT_FALSE(response == NULL);
1635
1636 EXPECT_TRUE(response->headers->IsKeepAlive());
1637 EXPECT_EQ(407, response->headers->response_code());
1638 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421639 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321640
1641 // The password prompt info should have been set in response->auth_challenge.
1642 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1643
[email protected]71e4573a2009-05-21 22:03:001644 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321645 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1646 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1647
1648 TestCompletionCallback callback2;
1649
1650 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441651 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421652 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321653
1654 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421655 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321656
1657 response = trans->GetResponseInfo();
1658 EXPECT_FALSE(response == NULL);
1659
1660 EXPECT_TRUE(response->headers->IsKeepAlive());
1661 EXPECT_EQ(407, response->headers->response_code());
1662 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421663 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321664
1665 // The password prompt info should have been set in response->auth_challenge.
1666 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1667
[email protected]71e4573a2009-05-21 22:03:001668 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321669 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1670 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131671
[email protected]e60e47a2010-07-14 03:37:181672 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1673 // out of scope.
1674 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321675}
1676
[email protected]a8e9b162009-03-12 00:06:441677// Test that we don't read the response body when we fail to establish a tunnel,
1678// even if the user cancels the proxy's auth attempt.
1679TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1680 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591681 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441682
[email protected]e44de5d2009-06-05 20:12:451683 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441684
[email protected]5695b8c2009-09-30 21:36:431685 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441686
[email protected]1c773ea12009-04-28 19:58:421687 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441688 request.method = "GET";
1689 request.url = GURL("https://www.google.com/");
1690 request.load_flags = 0;
1691
1692 // Since we have proxy, should try to establish tunnel.
1693 MockWrite data_writes[] = {
1694 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451695 "Host: www.google.com\r\n"
1696 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441697 };
1698
1699 // The proxy responds to the connect with a 407.
1700 MockRead data_reads[] = {
1701 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1702 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1703 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421704 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441705 };
1706
[email protected]31a2bfe2010-02-09 08:03:391707 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1708 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591709 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441710
1711 TestCompletionCallback callback;
1712
[email protected]5a1d7ca2010-04-28 20:12:271713 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421714 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441715
1716 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421717 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441718
[email protected]1c773ea12009-04-28 19:58:421719 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441720 EXPECT_FALSE(response == NULL);
1721
1722 EXPECT_TRUE(response->headers->IsKeepAlive());
1723 EXPECT_EQ(407, response->headers->response_code());
1724 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421725 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441726
1727 std::string response_data;
1728 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421729 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181730
1731 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1732 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441733}
1734
[email protected]8fdbcd22010-05-05 02:54:521735// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1736// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1737TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1738 // We are using a DIRECT connection (i.e. no proxy) for this session.
1739 SessionDependencies session_deps;
1740 scoped_ptr<HttpTransaction> trans(
1741 new HttpNetworkTransaction(CreateSession(&session_deps)));
1742
1743 HttpRequestInfo request;
1744 request.method = "GET";
1745 request.url = GURL("http://www.google.com/");
1746 request.load_flags = 0;
1747
1748 MockWrite data_writes1[] = {
1749 MockWrite("GET / HTTP/1.1\r\n"
1750 "Host: www.google.com\r\n"
1751 "Connection: keep-alive\r\n\r\n"),
1752 };
1753
1754 MockRead data_reads1[] = {
1755 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1756 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1757 // Large content-length -- won't matter, as connection will be reset.
1758 MockRead("Content-Length: 10000\r\n\r\n"),
1759 MockRead(false, ERR_FAILED),
1760 };
1761
1762 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1763 data_writes1, arraysize(data_writes1));
1764 session_deps.socket_factory.AddSocketDataProvider(&data1);
1765
1766 TestCompletionCallback callback;
1767
1768 int rv = trans->Start(&request, &callback, BoundNetLog());
1769 EXPECT_EQ(ERR_IO_PENDING, rv);
1770
1771 rv = callback.WaitForResult();
1772 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1773}
1774
[email protected]2df19bb2010-08-25 20:13:461775
1776// Test a simple get through an HTTPS Proxy.
1777TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1778 // Configure against https proxy server "proxy:70".
1779 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1780 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1781 session_deps.net_log = log.bound().net_log();
1782 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1783
[email protected]2df19bb2010-08-25 20:13:461784 HttpRequestInfo request;
1785 request.method = "GET";
1786 request.url = GURL("http://www.google.com/");
1787
1788 // Since we have proxy, should use full url
1789 MockWrite data_writes1[] = {
1790 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1791 "Host: www.google.com\r\n"
1792 "Proxy-Connection: keep-alive\r\n\r\n"),
1793 };
1794
1795 MockRead data_reads1[] = {
1796 MockRead("HTTP/1.1 200 OK\r\n"),
1797 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1798 MockRead("Content-Length: 100\r\n\r\n"),
1799 MockRead(false, OK),
1800 };
1801
1802 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1803 data_writes1, arraysize(data_writes1));
1804 session_deps.socket_factory.AddSocketDataProvider(&data1);
1805 SSLSocketDataProvider ssl(true, OK);
1806 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1807
1808 TestCompletionCallback callback1;
1809
[email protected]0b0bf032010-09-21 18:08:501810 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1811
[email protected]2df19bb2010-08-25 20:13:461812 int rv = trans->Start(&request, &callback1, log.bound());
1813 EXPECT_EQ(ERR_IO_PENDING, rv);
1814
1815 rv = callback1.WaitForResult();
1816 EXPECT_EQ(OK, rv);
1817
1818 const HttpResponseInfo* response = trans->GetResponseInfo();
1819 ASSERT_FALSE(response == NULL);
1820
1821 EXPECT_TRUE(response->headers->IsKeepAlive());
1822 EXPECT_EQ(200, response->headers->response_code());
1823 EXPECT_EQ(100, response->headers->GetContentLength());
1824 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1825
1826 // The password prompt info should not be set.
1827 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1828}
1829
[email protected]7642b5ae2010-09-01 20:55:171830// Test a SPDY get through an HTTPS Proxy.
1831TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
1832 // Configure against https proxy server "proxy:70".
1833 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1834 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1835 session_deps.net_log = log.bound().net_log();
1836 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1837
[email protected]7642b5ae2010-09-01 20:55:171838 HttpRequestInfo request;
1839 request.method = "GET";
1840 request.url = GURL("http://www.google.com/");
1841 request.load_flags = 0;
1842
1843 // fetch http://www.google.com/ via SPDY
1844 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1845 false));
1846 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1847
1848 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1849 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1850 MockRead spdy_reads[] = {
1851 CreateMockRead(*resp),
1852 CreateMockRead(*data),
1853 MockRead(true, 0, 0),
1854 };
1855
1856 scoped_refptr<DelayedSocketData> spdy_data(
1857 new DelayedSocketData(
1858 1, // wait for one write to finish before reading.
1859 spdy_reads, arraysize(spdy_reads),
1860 spdy_writes, arraysize(spdy_writes)));
1861 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1862
1863 SSLSocketDataProvider ssl(true, OK);
1864 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1865 ssl.next_proto = "spdy/2";
1866 ssl.was_npn_negotiated = true;
1867 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1868
1869 TestCompletionCallback callback1;
1870
[email protected]0b0bf032010-09-21 18:08:501871 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1872
[email protected]7642b5ae2010-09-01 20:55:171873 int rv = trans->Start(&request, &callback1, log.bound());
1874 EXPECT_EQ(ERR_IO_PENDING, rv);
1875
1876 rv = callback1.WaitForResult();
1877 EXPECT_EQ(OK, rv);
1878
1879 const HttpResponseInfo* response = trans->GetResponseInfo();
1880 ASSERT_TRUE(response != NULL);
1881 ASSERT_TRUE(response->headers != NULL);
1882 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1883
1884 std::string response_data;
1885 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1886 EXPECT_EQ(net::kUploadData, response_data);
1887}
1888
[email protected]2df19bb2010-08-25 20:13:461889// Test the challenge-response-retry sequence through an HTTPS Proxy
1890TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
1891 // Configure against https proxy server "proxy:70".
1892 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
1893 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1894 session_deps.net_log = log.bound().net_log();
1895 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1896
[email protected]2df19bb2010-08-25 20:13:461897 HttpRequestInfo request;
1898 request.method = "GET";
1899 request.url = GURL("http://www.google.com/");
1900 // when the no authentication data flag is set.
1901 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1902
1903 // Since we have proxy, should use full url
1904 MockWrite data_writes1[] = {
1905 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1906 "Host: www.google.com\r\n"
1907 "Proxy-Connection: keep-alive\r\n\r\n"),
1908
1909 // After calling trans->RestartWithAuth(), this is the request we should
1910 // be issuing -- the final header line contains the credentials.
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 // The proxy responds to the GET with a 407, using a persistent
1918 // connection.
1919 MockRead data_reads1[] = {
1920 // No credentials.
1921 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1922 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1923 MockRead("Proxy-Connection: keep-alive\r\n"),
1924 MockRead("Content-Length: 0\r\n\r\n"),
1925
1926 MockRead("HTTP/1.1 200 OK\r\n"),
1927 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1928 MockRead("Content-Length: 100\r\n\r\n"),
1929 MockRead(false, OK),
1930 };
1931
1932 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1933 data_writes1, arraysize(data_writes1));
1934 session_deps.socket_factory.AddSocketDataProvider(&data1);
1935 SSLSocketDataProvider ssl(true, OK);
1936 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1937
1938 TestCompletionCallback callback1;
1939
[email protected]0b0bf032010-09-21 18:08:501940 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1941
[email protected]2df19bb2010-08-25 20:13:461942 int rv = trans->Start(&request, &callback1, log.bound());
1943 EXPECT_EQ(ERR_IO_PENDING, rv);
1944
1945 rv = callback1.WaitForResult();
1946 EXPECT_EQ(OK, rv);
1947
1948 const HttpResponseInfo* response = trans->GetResponseInfo();
1949 ASSERT_FALSE(response == NULL);
1950
1951 EXPECT_EQ(407, response->headers->response_code());
1952 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1953
1954 // The password prompt info should have been set in response->auth_challenge.
1955 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1956
1957 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
1958 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1959 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1960
1961 TestCompletionCallback callback2;
1962
1963 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1964 EXPECT_EQ(ERR_IO_PENDING, rv);
1965
1966 rv = callback2.WaitForResult();
1967 EXPECT_EQ(OK, rv);
1968
1969 response = trans->GetResponseInfo();
1970 ASSERT_FALSE(response == NULL);
1971
1972 EXPECT_TRUE(response->headers->IsKeepAlive());
1973 EXPECT_EQ(200, response->headers->response_code());
1974 EXPECT_EQ(100, response->headers->GetContentLength());
1975 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1976
1977 // The password prompt info should not be set.
1978 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1979}
1980
[email protected]ff007e162009-05-23 09:13:151981void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:081982 const MockRead& status, int expected_status) {
1983 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:591984 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:081985
[email protected]228ff742009-06-05 01:19:591986 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:081987
[email protected]1c773ea12009-04-28 19:58:421988 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:081989 request.method = "GET";
1990 request.url = GURL("https://www.google.com/");
1991 request.load_flags = 0;
1992
1993 // Since we have proxy, should try to establish tunnel.
1994 MockWrite data_writes[] = {
1995 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451996 "Host: www.google.com\r\n"
1997 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:081998 };
1999
2000 MockRead data_reads[] = {
2001 status,
2002 MockRead("Content-Length: 10\r\n\r\n"),
2003 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422004 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082005 };
2006
[email protected]31a2bfe2010-02-09 08:03:392007 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2008 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592009 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082010
2011 TestCompletionCallback callback;
2012
[email protected]0b0bf032010-09-21 18:08:502013 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2014
[email protected]5a1d7ca2010-04-28 20:12:272015 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422016 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082017
2018 rv = callback.WaitForResult();
2019 EXPECT_EQ(expected_status, rv);
2020}
2021
[email protected]ff007e162009-05-23 09:13:152022void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082023 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422024 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082025}
2026
2027TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2028 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2029}
2030
2031TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2032 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2033}
2034
2035TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2036 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2037}
2038
2039TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2040 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2041}
2042
2043TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2044 ConnectStatusHelper(
2045 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2046}
2047
2048TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2049 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2050}
2051
2052TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2053 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2054}
2055
2056TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2057 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2058}
2059
2060TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2061 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2062}
2063
2064TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2065 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2066}
2067
2068TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2069 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2070}
2071
2072TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2073 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2074}
2075
2076TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2077 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2078}
2079
2080TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2081 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2082}
2083
2084TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2085 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2086}
2087
2088TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2089 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2090}
2091
2092TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2093 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2094}
2095
2096TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2097 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2098}
2099
2100TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2101 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2102}
2103
2104TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2105 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2106}
2107
2108TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2109 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2110}
2111
2112TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2113 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2114}
2115
2116TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2117 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2118}
2119
2120TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2121 ConnectStatusHelperWithExpectedStatus(
2122 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542123 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082124}
2125
2126TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2127 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2128}
2129
2130TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2131 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2132}
2133
2134TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2135 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2136}
2137
2138TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2139 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2140}
2141
2142TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2143 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2144}
2145
2146TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2147 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2148}
2149
2150TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2151 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2152}
2153
2154TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2155 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2156}
2157
2158TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2159 ConnectStatusHelper(
2160 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2161}
2162
2163TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2164 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2165}
2166
2167TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2168 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2169}
2170
2171TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2172 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2173}
2174
2175TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2176 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2177}
2178
2179TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2180 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2181}
2182
2183TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2184 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2185}
2186
2187TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2188 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2189}
2190
[email protected]038e9a32008-10-08 22:40:162191// Test the flow when both the proxy server AND origin server require
2192// authentication. Again, this uses basic auth for both since that is
2193// the simplest to mock.
2194TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]228ff742009-06-05 01:19:592195 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012196
[email protected]038e9a32008-10-08 22:40:162197 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422198 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432199 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162200
[email protected]1c773ea12009-04-28 19:58:422201 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162202 request.method = "GET";
2203 request.url = GURL("http://www.google.com/");
2204 request.load_flags = 0;
2205
[email protected]f9ee6b52008-11-08 06:46:232206 MockWrite data_writes1[] = {
2207 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2208 "Host: www.google.com\r\n"
2209 "Proxy-Connection: keep-alive\r\n\r\n"),
2210 };
2211
[email protected]038e9a32008-10-08 22:40:162212 MockRead data_reads1[] = {
2213 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2214 // Give a couple authenticate options (only the middle one is actually
2215 // supported).
[email protected]22927ad2009-09-21 19:56:192216 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162217 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2218 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2219 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2220 // Large content-length -- won't matter, as connection will be reset.
2221 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422222 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162223 };
2224
2225 // After calling trans->RestartWithAuth() the first time, this is the
2226 // request we should be issuing -- the final header line contains the
2227 // proxy's credentials.
2228 MockWrite data_writes2[] = {
2229 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2230 "Host: www.google.com\r\n"
2231 "Proxy-Connection: keep-alive\r\n"
2232 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2233 };
2234
2235 // Now the proxy server lets the request pass through to origin server.
2236 // The origin server responds with a 401.
2237 MockRead data_reads2[] = {
2238 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2239 // Note: We are using the same realm-name as the proxy server. This is
2240 // completely valid, as realms are unique across hosts.
2241 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2242 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2243 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422244 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162245 };
2246
2247 // After calling trans->RestartWithAuth() the second time, we should send
2248 // the credentials for both the proxy and origin server.
2249 MockWrite data_writes3[] = {
2250 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2251 "Host: www.google.com\r\n"
2252 "Proxy-Connection: keep-alive\r\n"
2253 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2254 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2255 };
2256
2257 // Lastly we get the desired content.
2258 MockRead data_reads3[] = {
2259 MockRead("HTTP/1.0 200 OK\r\n"),
2260 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2261 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422262 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162263 };
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]038e9a32008-10-08 22:40:162274
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]038e9a32008-10-08 22:40:162279
2280 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422281 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162282
[email protected]1c773ea12009-04-28 19:58:422283 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162284 EXPECT_FALSE(response == NULL);
2285
2286 // The password prompt info should have been set in response->auth_challenge.
2287 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2288
[email protected]71e4573a2009-05-21 22:03:002289 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162290 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2291 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2292
2293 TestCompletionCallback callback2;
2294
[email protected]13c8a092010-07-29 06:15:442295 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422296 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162297
2298 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422299 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162300
2301 response = trans->GetResponseInfo();
2302 EXPECT_FALSE(response == NULL);
2303 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2304
[email protected]71e4573a2009-05-21 22:03:002305 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162306 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2307 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2308
2309 TestCompletionCallback callback3;
2310
[email protected]13c8a092010-07-29 06:15:442311 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422312 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162313
2314 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422315 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162316
2317 response = trans->GetResponseInfo();
2318 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2319 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162320}
[email protected]4ddaf2502008-10-23 18:26:192321
[email protected]ea9dc9a2009-09-05 00:43:322322// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2323// can't hook into its internals to cause it to generate predictable NTLM
2324// authorization headers.
2325#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292326// The NTLM authentication unit tests were generated by capturing the HTTP
2327// requests and responses using Fiddler 2 and inspecting the generated random
2328// bytes in the debugger.
2329
2330// Enter the correct password and authenticate successfully.
2331TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422332 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112333 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592334 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502335 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3f918782009-02-28 01:29:242336
[email protected]1c773ea12009-04-28 19:58:422337 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242338 request.method = "GET";
2339 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2340 request.load_flags = 0;
2341
2342 MockWrite data_writes1[] = {
2343 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2344 "Host: 172.22.68.17\r\n"
2345 "Connection: keep-alive\r\n\r\n"),
2346 };
2347
2348 MockRead data_reads1[] = {
2349 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042350 // Negotiate and NTLM are often requested together. However, we only want
2351 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2352 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242353 MockRead("WWW-Authenticate: NTLM\r\n"),
2354 MockRead("Connection: close\r\n"),
2355 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362356 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242357 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422358 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242359 };
2360
2361 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222362 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242363 // request we should be issuing -- the final header line contains a Type
2364 // 1 message.
2365 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2366 "Host: 172.22.68.17\r\n"
2367 "Connection: keep-alive\r\n"
2368 "Authorization: NTLM "
2369 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2370
2371 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2372 // (the credentials for the origin server). The second request continues
2373 // on the same connection.
2374 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2375 "Host: 172.22.68.17\r\n"
2376 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292377 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2378 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2379 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2380 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2381 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242382 };
2383
2384 MockRead data_reads2[] = {
2385 // The origin server responds with a Type 2 message.
2386 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2387 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292388 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242389 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2390 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2391 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2392 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2393 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2394 "BtAAAAAAA=\r\n"),
2395 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362396 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242397 MockRead("You are not authorized to view this page\r\n"),
2398
2399 // Lastly we get the desired content.
2400 MockRead("HTTP/1.1 200 OK\r\n"),
2401 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2402 MockRead("Content-Length: 13\r\n\r\n"),
2403 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422404 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242405 };
2406
[email protected]31a2bfe2010-02-09 08:03:392407 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2408 data_writes1, arraysize(data_writes1));
2409 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2410 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592411 session_deps.socket_factory.AddSocketDataProvider(&data1);
2412 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242413
2414 TestCompletionCallback callback1;
2415
[email protected]0b0bf032010-09-21 18:08:502416 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2417
[email protected]5a1d7ca2010-04-28 20:12:272418 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422419 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242420
2421 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422422 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242423
[email protected]0757e7702009-03-27 04:00:222424 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2425 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442426 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422427 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222428 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422429 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222430 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2431
[email protected]1c773ea12009-04-28 19:58:422432 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042433 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242434
[email protected]aef04272010-06-28 18:03:042435 // The password prompt info should have been set in
2436 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242437 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2438
[email protected]71e4573a2009-05-21 22:03:002439 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242440 EXPECT_EQ(L"", response->auth_challenge->realm);
2441 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2442
[email protected]0757e7702009-03-27 04:00:222443 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242444
[email protected]13c8a092010-07-29 06:15:442445 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422446 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242447
[email protected]0757e7702009-03-27 04:00:222448 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422449 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242450
2451 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042452 ASSERT_FALSE(response == NULL);
2453
[email protected]3f918782009-02-28 01:29:242454 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2455 EXPECT_EQ(13, response->headers->GetContentLength());
2456}
2457
[email protected]385a4672009-03-11 22:21:292458// Enter a wrong password, and then the correct one.
2459TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422460 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112461 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592462 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502463 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]385a4672009-03-11 22:21:292464
[email protected]1c773ea12009-04-28 19:58:422465 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292466 request.method = "GET";
2467 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2468 request.load_flags = 0;
2469
2470 MockWrite data_writes1[] = {
2471 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2472 "Host: 172.22.68.17\r\n"
2473 "Connection: keep-alive\r\n\r\n"),
2474 };
2475
2476 MockRead data_reads1[] = {
2477 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042478 // Negotiate and NTLM are often requested together. However, we only want
2479 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2480 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292481 MockRead("WWW-Authenticate: NTLM\r\n"),
2482 MockRead("Connection: close\r\n"),
2483 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362484 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292485 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422486 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292487 };
2488
2489 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222490 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292491 // request we should be issuing -- the final header line contains a Type
2492 // 1 message.
2493 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2494 "Host: 172.22.68.17\r\n"
2495 "Connection: keep-alive\r\n"
2496 "Authorization: NTLM "
2497 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2498
2499 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2500 // (the credentials for the origin server). The second request continues
2501 // on the same connection.
2502 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2503 "Host: 172.22.68.17\r\n"
2504 "Connection: keep-alive\r\n"
2505 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2506 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2507 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2508 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2509 "4Ww7b7E=\r\n\r\n"),
2510 };
2511
2512 MockRead data_reads2[] = {
2513 // The origin server responds with a Type 2 message.
2514 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2515 MockRead("WWW-Authenticate: NTLM "
2516 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2517 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2518 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2519 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2520 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2521 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2522 "BtAAAAAAA=\r\n"),
2523 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362524 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292525 MockRead("You are not authorized to view this page\r\n"),
2526
2527 // Wrong password.
2528 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292529 MockRead("WWW-Authenticate: NTLM\r\n"),
2530 MockRead("Connection: close\r\n"),
2531 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362532 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292533 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422534 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292535 };
2536
2537 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222538 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292539 // request we should be issuing -- the final header line contains a Type
2540 // 1 message.
2541 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2542 "Host: 172.22.68.17\r\n"
2543 "Connection: keep-alive\r\n"
2544 "Authorization: NTLM "
2545 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2546
2547 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2548 // (the credentials for the origin server). The second request continues
2549 // on the same connection.
2550 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2551 "Host: 172.22.68.17\r\n"
2552 "Connection: keep-alive\r\n"
2553 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2554 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2555 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2556 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2557 "+4MUm7c=\r\n\r\n"),
2558 };
2559
2560 MockRead data_reads3[] = {
2561 // The origin server responds with a Type 2 message.
2562 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2563 MockRead("WWW-Authenticate: NTLM "
2564 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2565 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2566 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2567 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2568 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2569 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2570 "BtAAAAAAA=\r\n"),
2571 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362572 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292573 MockRead("You are not authorized to view this page\r\n"),
2574
2575 // Lastly we get the desired content.
2576 MockRead("HTTP/1.1 200 OK\r\n"),
2577 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2578 MockRead("Content-Length: 13\r\n\r\n"),
2579 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422580 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292581 };
2582
[email protected]31a2bfe2010-02-09 08:03:392583 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2584 data_writes1, arraysize(data_writes1));
2585 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2586 data_writes2, arraysize(data_writes2));
2587 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2588 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592589 session_deps.socket_factory.AddSocketDataProvider(&data1);
2590 session_deps.socket_factory.AddSocketDataProvider(&data2);
2591 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292592
2593 TestCompletionCallback callback1;
2594
[email protected]0b0bf032010-09-21 18:08:502595 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2596
[email protected]5a1d7ca2010-04-28 20:12:272597 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422598 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292599
2600 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422601 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292602
[email protected]0757e7702009-03-27 04:00:222603 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292604 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442605 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422606 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292607 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422608 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222609 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:292610
[email protected]1c773ea12009-04-28 19:58:422611 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:292612 EXPECT_FALSE(response == NULL);
2613
2614 // The password prompt info should have been set in response->auth_challenge.
2615 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2616
[email protected]71e4573a2009-05-21 22:03:002617 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:292618 EXPECT_EQ(L"", response->auth_challenge->realm);
2619 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2620
2621 TestCompletionCallback callback3;
2622
[email protected]0757e7702009-03-27 04:00:222623 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:442624 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:422625 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:292626
2627 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422628 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:292629
[email protected]0757e7702009-03-27 04:00:222630 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2631 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:442632 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:422633 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222634 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422635 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222636 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2637
2638 response = trans->GetResponseInfo();
2639 EXPECT_FALSE(response == NULL);
2640
2641 // The password prompt info should have been set in response->auth_challenge.
2642 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2643
[email protected]71e4573a2009-05-21 22:03:002644 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:222645 EXPECT_EQ(L"", response->auth_challenge->realm);
2646 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2647
2648 TestCompletionCallback callback5;
2649
2650 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:442651 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:422652 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222653
2654 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422655 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222656
[email protected]385a4672009-03-11 22:21:292657 response = trans->GetResponseInfo();
2658 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2659 EXPECT_EQ(13, response->headers->GetContentLength());
2660}
[email protected]ea9dc9a2009-09-05 00:43:322661#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:292662
[email protected]4ddaf2502008-10-23 18:26:192663// Test reading a server response which has only headers, and no body.
2664// After some maximum number of bytes is consumed, the transaction should
2665// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
2666TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:592667 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:402668 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:432669 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:192670
[email protected]1c773ea12009-04-28 19:58:422671 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:192672 request.method = "GET";
2673 request.url = GURL("http://www.google.com/");
2674 request.load_flags = 0;
2675
[email protected]b75b7b2f2009-10-06 00:54:532676 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:432677 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:532678 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:192679
2680 MockRead data_reads[] = {
2681 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:432682 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:192683 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:422684 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:192685 };
[email protected]31a2bfe2010-02-09 08:03:392686 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592687 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:192688
2689 TestCompletionCallback callback;
2690
[email protected]5a1d7ca2010-04-28 20:12:272691 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422692 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:192693
2694 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422695 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:192696
[email protected]1c773ea12009-04-28 19:58:422697 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:192698 EXPECT_TRUE(response == NULL);
2699}
[email protected]f4e426b2008-11-05 00:24:492700
2701// Make sure that we don't try to reuse a TCPClientSocket when failing to
2702// establish tunnel.
2703// http://code.google.com/p/chromium/issues/detail?id=3772
2704TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
2705 // Configure against proxy server "myproxy:70".
[email protected]228ff742009-06-05 01:19:592706 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012707
[email protected]228ff742009-06-05 01:19:592708 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:492709
[email protected]5695b8c2009-09-30 21:36:432710 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:492711
[email protected]1c773ea12009-04-28 19:58:422712 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:492713 request.method = "GET";
2714 request.url = GURL("https://www.google.com/");
2715 request.load_flags = 0;
2716
2717 // Since we have proxy, should try to establish tunnel.
2718 MockWrite data_writes1[] = {
2719 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452720 "Host: www.google.com\r\n"
2721 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:492722 };
2723
[email protected]77848d12008-11-14 00:00:222724 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:492725 // connection. Usually a proxy would return 501 (not implemented),
2726 // or 200 (tunnel established).
2727 MockRead data_reads1[] = {
2728 MockRead("HTTP/1.1 404 Not Found\r\n"),
2729 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422730 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:492731 };
2732
[email protected]31a2bfe2010-02-09 08:03:392733 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2734 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:592735 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:492736
2737 TestCompletionCallback callback1;
2738
[email protected]5a1d7ca2010-04-28 20:12:272739 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422740 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:492741
2742 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422743 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:492744
[email protected]1c773ea12009-04-28 19:58:422745 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:082746 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:492747
[email protected]b4404c02009-04-10 16:38:522748 // Empty the current queue. This is necessary because idle sockets are
2749 // added to the connection pool asynchronously with a PostTask.
2750 MessageLoop::current()->RunAllPending();
2751
[email protected]f4e426b2008-11-05 00:24:492752 // We now check to make sure the TCPClientSocket was not added back to
2753 // the pool.
[email protected]a937a06d2009-08-19 21:19:242754 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492755 trans.reset();
[email protected]b4404c02009-04-10 16:38:522756 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:492757 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:242758 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:492759}
[email protected]372d34a2008-11-05 21:30:512760
[email protected]1b157c02009-04-21 01:55:402761// Make sure that we recycle a socket after reading all of the response body.
2762TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:592763 SessionDependencies session_deps;
2764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:402765
[email protected]5695b8c2009-09-30 21:36:432766 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:402767
[email protected]1c773ea12009-04-28 19:58:422768 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:402769 request.method = "GET";
2770 request.url = GURL("http://www.google.com/");
2771 request.load_flags = 0;
2772
2773 MockRead data_reads[] = {
2774 // A part of the response body is received with the response headers.
2775 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
2776 // The rest of the response body is received in two parts.
2777 MockRead("lo"),
2778 MockRead(" world"),
2779 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422780 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:402781 };
2782
[email protected]31a2bfe2010-02-09 08:03:392783 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592784 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:402785
2786 TestCompletionCallback callback;
2787
[email protected]5a1d7ca2010-04-28 20:12:272788 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422789 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:402790
2791 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422792 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402793
[email protected]1c773ea12009-04-28 19:58:422794 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:402795 EXPECT_TRUE(response != NULL);
2796
2797 EXPECT_TRUE(response->headers != NULL);
2798 std::string status_line = response->headers->GetStatusLine();
2799 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
2800
[email protected]a937a06d2009-08-19 21:19:242801 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402802
2803 std::string response_data;
2804 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:422805 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:402806 EXPECT_EQ("hello world", response_data);
2807
2808 // Empty the current queue. This is necessary because idle sockets are
2809 // added to the connection pool asynchronously with a PostTask.
2810 MessageLoop::current()->RunAllPending();
2811
2812 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:242813 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:402814}
2815
[email protected]76a505b2010-08-25 06:23:002816// Make sure that we recycle a SSL socket after reading all of the response
2817// body.
2818TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
2819 SessionDependencies session_deps;
2820 HttpRequestInfo request;
2821 request.method = "GET";
2822 request.url = GURL("https://www.google.com/");
2823 request.load_flags = 0;
2824
2825 MockWrite data_writes[] = {
2826 MockWrite("GET / HTTP/1.1\r\n"
2827 "Host: www.google.com\r\n"
2828 "Connection: keep-alive\r\n\r\n"),
2829 };
2830
2831 MockRead data_reads[] = {
2832 MockRead("HTTP/1.1 200 OK\r\n"),
2833 MockRead("Content-Length: 11\r\n\r\n"),
2834 MockRead("hello world"),
2835 MockRead(false, OK),
2836 };
2837
2838 SSLSocketDataProvider ssl(true, OK);
2839 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2840
2841 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2842 data_writes, arraysize(data_writes));
2843 session_deps.socket_factory.AddSocketDataProvider(&data);
2844
2845 TestCompletionCallback callback;
2846
2847 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2848 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2849
2850 int rv = trans->Start(&request, &callback, BoundNetLog());
2851
2852 EXPECT_EQ(ERR_IO_PENDING, rv);
2853 EXPECT_EQ(OK, callback.WaitForResult());
2854
2855 const HttpResponseInfo* response = trans->GetResponseInfo();
2856 ASSERT_TRUE(response != NULL);
2857 ASSERT_TRUE(response->headers != NULL);
2858 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2859
2860 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2861
2862 std::string response_data;
2863 rv = ReadTransaction(trans.get(), &response_data);
2864 EXPECT_EQ(OK, rv);
2865 EXPECT_EQ("hello world", response_data);
2866
2867 // Empty the current queue. This is necessary because idle sockets are
2868 // added to the connection pool asynchronously with a PostTask.
2869 MessageLoop::current()->RunAllPending();
2870
2871 // We now check to make sure the socket was added back to the pool.
2872 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2873}
2874
2875// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
2876// from the pool and make sure that we recover okay.
2877TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
2878 SessionDependencies session_deps;
2879 HttpRequestInfo request;
2880 request.method = "GET";
2881 request.url = GURL("https://www.google.com/");
2882 request.load_flags = 0;
2883
2884 MockWrite data_writes[] = {
2885 MockWrite("GET / HTTP/1.1\r\n"
2886 "Host: www.google.com\r\n"
2887 "Connection: keep-alive\r\n\r\n"),
2888 MockWrite("GET / HTTP/1.1\r\n"
2889 "Host: www.google.com\r\n"
2890 "Connection: keep-alive\r\n\r\n"),
2891 };
2892
2893 MockRead data_reads[] = {
2894 MockRead("HTTP/1.1 200 OK\r\n"),
2895 MockRead("Content-Length: 11\r\n\r\n"),
2896 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
2897 MockRead("hello world"),
2898 MockRead(true, 0, 0) // EOF
2899 };
2900
2901 SSLSocketDataProvider ssl(true, OK);
2902 SSLSocketDataProvider ssl2(true, OK);
2903 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2904 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2905
2906 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2907 data_writes, arraysize(data_writes));
2908 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
2909 data_writes, arraysize(data_writes));
2910 session_deps.socket_factory.AddSocketDataProvider(&data);
2911 session_deps.socket_factory.AddSocketDataProvider(&data2);
2912
2913 TestCompletionCallback callback;
2914
2915 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2916 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2917
2918 int rv = trans->Start(&request, &callback, BoundNetLog());
2919
2920 EXPECT_EQ(ERR_IO_PENDING, rv);
2921 EXPECT_EQ(OK, callback.WaitForResult());
2922
2923 const HttpResponseInfo* response = trans->GetResponseInfo();
2924 ASSERT_TRUE(response != NULL);
2925 ASSERT_TRUE(response->headers != NULL);
2926 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2927
2928 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2929
2930 std::string response_data;
2931 rv = ReadTransaction(trans.get(), &response_data);
2932 EXPECT_EQ(OK, rv);
2933 EXPECT_EQ("hello world", response_data);
2934
2935 // Empty the current queue. This is necessary because idle sockets are
2936 // added to the connection pool asynchronously with a PostTask.
2937 MessageLoop::current()->RunAllPending();
2938
2939 // We now check to make sure the socket was added back to the pool.
2940 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2941
2942 // Now start the second transaction, which should reuse the previous socket.
2943
2944 trans.reset(new HttpNetworkTransaction(session));
2945
2946 rv = trans->Start(&request, &callback, BoundNetLog());
2947
2948 EXPECT_EQ(ERR_IO_PENDING, rv);
2949 EXPECT_EQ(OK, callback.WaitForResult());
2950
2951 response = trans->GetResponseInfo();
2952 ASSERT_TRUE(response != NULL);
2953 ASSERT_TRUE(response->headers != NULL);
2954 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2955
2956 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
2957
2958 rv = ReadTransaction(trans.get(), &response_data);
2959 EXPECT_EQ(OK, rv);
2960 EXPECT_EQ("hello world", response_data);
2961
2962 // Empty the current queue. This is necessary because idle sockets are
2963 // added to the connection pool asynchronously with a PostTask.
2964 MessageLoop::current()->RunAllPending();
2965
2966 // We now check to make sure the socket was added back to the pool.
2967 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
2968}
2969
[email protected]b4404c02009-04-10 16:38:522970// Make sure that we recycle a socket after a zero-length response.
2971// http://crbug.com/9880
2972TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:592973 SessionDependencies session_deps;
2974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:522975
[email protected]5695b8c2009-09-30 21:36:432976 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:522977
[email protected]1c773ea12009-04-28 19:58:422978 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:522979 request.method = "GET";
2980 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
2981 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
2982 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
2983 "rt=prt.2642,ol.2649,xjs.2951");
2984 request.load_flags = 0;
2985
2986 MockRead data_reads[] = {
2987 MockRead("HTTP/1.1 204 No Content\r\n"
2988 "Content-Length: 0\r\n"
2989 "Content-Type: text/html\r\n\r\n"),
2990 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:422991 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:522992 };
2993
[email protected]31a2bfe2010-02-09 08:03:392994 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:592995 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:522996
2997 TestCompletionCallback callback;
2998
[email protected]5a1d7ca2010-04-28 20:12:272999 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423000 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523001
3002 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423003 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523004
[email protected]1c773ea12009-04-28 19:58:423005 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523006 EXPECT_TRUE(response != NULL);
3007
3008 EXPECT_TRUE(response->headers != NULL);
3009 std::string status_line = response->headers->GetStatusLine();
3010 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3011
[email protected]a937a06d2009-08-19 21:19:243012 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523013
3014 std::string response_data;
3015 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423016 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523017 EXPECT_EQ("", response_data);
3018
3019 // Empty the current queue. This is necessary because idle sockets are
3020 // added to the connection pool asynchronously with a PostTask.
3021 MessageLoop::current()->RunAllPending();
3022
3023 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243024 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523025}
3026
[email protected]372d34a2008-11-05 21:30:513027TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423028 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513029 // Transaction 1: a GET request that succeeds. The socket is recycled
3030 // after use.
3031 request[0].method = "GET";
3032 request[0].url = GURL("http://www.google.com/");
3033 request[0].load_flags = 0;
3034 // Transaction 2: a POST request. Reuses the socket kept alive from
3035 // transaction 1. The first attempts fails when writing the POST data.
3036 // This causes the transaction to retry with a new socket. The second
3037 // attempt succeeds.
3038 request[1].method = "POST";
3039 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423040 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513041 request[1].upload_data->AppendBytes("foo", 3);
3042 request[1].load_flags = 0;
3043
[email protected]228ff742009-06-05 01:19:593044 SessionDependencies session_deps;
3045 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]372d34a2008-11-05 21:30:513046
3047 // The first socket is used for transaction 1 and the first attempt of
3048 // transaction 2.
3049
3050 // The response of transaction 1.
3051 MockRead data_reads1[] = {
3052 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3053 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423054 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513055 };
3056 // The mock write results of transaction 1 and the first attempt of
3057 // transaction 2.
3058 MockWrite data_writes1[] = {
3059 MockWrite(false, 64), // GET
3060 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423061 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513062 };
[email protected]31a2bfe2010-02-09 08:03:393063 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3064 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513065
3066 // The second socket is used for the second attempt of transaction 2.
3067
3068 // The response of transaction 2.
3069 MockRead data_reads2[] = {
3070 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3071 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423072 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513073 };
3074 // The mock write results of the second attempt of transaction 2.
3075 MockWrite data_writes2[] = {
3076 MockWrite(false, 93), // POST
3077 MockWrite(false, 3), // POST data
3078 };
[email protected]31a2bfe2010-02-09 08:03:393079 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3080 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513081
[email protected]5ecc992a42009-11-11 01:41:593082 session_deps.socket_factory.AddSocketDataProvider(&data1);
3083 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513084
3085 const char* kExpectedResponseData[] = {
3086 "hello world", "welcome"
3087 };
3088
3089 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423090 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433091 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513092
3093 TestCompletionCallback callback;
3094
[email protected]5a1d7ca2010-04-28 20:12:273095 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423096 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513097
3098 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423099 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513100
[email protected]1c773ea12009-04-28 19:58:423101 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513102 EXPECT_TRUE(response != NULL);
3103
3104 EXPECT_TRUE(response->headers != NULL);
3105 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3106
3107 std::string response_data;
3108 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423109 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513110 EXPECT_EQ(kExpectedResponseData[i], response_data);
3111 }
3112}
[email protected]f9ee6b52008-11-08 06:46:233113
3114// Test the request-challenge-retry sequence for basic auth when there is
3115// an identity in the URL. The request should be sent as normal, but when
3116// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323117TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:593118 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403119 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433120 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:233121
[email protected]1c773ea12009-04-28 19:58:423122 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233123 request.method = "GET";
3124 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293125 request.url = GURL("http://foo:b@[email protected]/");
3126
3127 // The password contains an escaped character -- for this test to pass it
3128 // will need to be unescaped by HttpNetworkTransaction.
3129 EXPECT_EQ("b%40r", request.url.password());
3130
[email protected]ea9dc9a2009-09-05 00:43:323131 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233132
3133 MockWrite data_writes1[] = {
3134 MockWrite("GET / HTTP/1.1\r\n"
3135 "Host: www.google.com\r\n"
3136 "Connection: keep-alive\r\n\r\n"),
3137 };
3138
3139 MockRead data_reads1[] = {
3140 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3141 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3142 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423143 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233144 };
3145
3146 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323147 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233148 MockWrite data_writes2[] = {
3149 MockWrite("GET / HTTP/1.1\r\n"
3150 "Host: www.google.com\r\n"
3151 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293152 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233153 };
3154
3155 MockRead data_reads2[] = {
3156 MockRead("HTTP/1.0 200 OK\r\n"),
3157 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423158 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233159 };
3160
[email protected]31a2bfe2010-02-09 08:03:393161 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3162 data_writes1, arraysize(data_writes1));
3163 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3164 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593165 session_deps.socket_factory.AddSocketDataProvider(&data1);
3166 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233167
3168 TestCompletionCallback callback1;
3169
[email protected]5a1d7ca2010-04-28 20:12:273170 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423171 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233172
3173 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423174 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233175
[email protected]0757e7702009-03-27 04:00:223176 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3177 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443178 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423179 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223180 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423181 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223182 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3183
[email protected]1c773ea12009-04-28 19:58:423184 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233185 EXPECT_FALSE(response == NULL);
3186
3187 // There is no challenge info, since the identity in URL worked.
3188 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3189
3190 EXPECT_EQ(100, response->headers->GetContentLength());
3191
3192 // Empty the current queue.
3193 MessageLoop::current()->RunAllPending();
3194}
3195
[email protected]ea9dc9a2009-09-05 00:43:323196// Test the request-challenge-retry sequence for basic auth when there is
3197// an incorrect identity in the URL. The identity from the URL should be used
3198// only once.
3199TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3200 SessionDependencies session_deps;
3201 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433202 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323203
3204 HttpRequestInfo request;
3205 request.method = "GET";
3206 // Note: the URL has a username:password in it. The password "baz" is
3207 // wrong (should be "bar").
3208 request.url = GURL("http://foo:[email protected]/");
3209
3210 request.load_flags = LOAD_NORMAL;
3211
3212 MockWrite data_writes1[] = {
3213 MockWrite("GET / HTTP/1.1\r\n"
3214 "Host: www.google.com\r\n"
3215 "Connection: keep-alive\r\n\r\n"),
3216 };
3217
3218 MockRead data_reads1[] = {
3219 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3220 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3221 MockRead("Content-Length: 10\r\n\r\n"),
3222 MockRead(false, ERR_FAILED),
3223 };
3224
3225 // After the challenge above, the transaction will be restarted using the
3226 // identity from the url (foo, baz) to answer the challenge.
3227 MockWrite data_writes2[] = {
3228 MockWrite("GET / HTTP/1.1\r\n"
3229 "Host: www.google.com\r\n"
3230 "Connection: keep-alive\r\n"
3231 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3232 };
3233
3234 MockRead data_reads2[] = {
3235 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3236 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3237 MockRead("Content-Length: 10\r\n\r\n"),
3238 MockRead(false, ERR_FAILED),
3239 };
3240
3241 // After the challenge above, the transaction will be restarted using the
3242 // identity supplied by the user (foo, bar) to answer the challenge.
3243 MockWrite data_writes3[] = {
3244 MockWrite("GET / HTTP/1.1\r\n"
3245 "Host: www.google.com\r\n"
3246 "Connection: keep-alive\r\n"
3247 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3248 };
3249
3250 MockRead data_reads3[] = {
3251 MockRead("HTTP/1.0 200 OK\r\n"),
3252 MockRead("Content-Length: 100\r\n\r\n"),
3253 MockRead(false, OK),
3254 };
3255
[email protected]31a2bfe2010-02-09 08:03:393256 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3257 data_writes1, arraysize(data_writes1));
3258 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3259 data_writes2, arraysize(data_writes2));
3260 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3261 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593262 session_deps.socket_factory.AddSocketDataProvider(&data1);
3263 session_deps.socket_factory.AddSocketDataProvider(&data2);
3264 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323265
3266 TestCompletionCallback callback1;
3267
[email protected]5a1d7ca2010-04-28 20:12:273268 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323269 EXPECT_EQ(ERR_IO_PENDING, rv);
3270
3271 rv = callback1.WaitForResult();
3272 EXPECT_EQ(OK, rv);
3273
3274 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3275 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443276 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323277 EXPECT_EQ(ERR_IO_PENDING, rv);
3278 rv = callback2.WaitForResult();
3279 EXPECT_EQ(OK, rv);
3280 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3281
3282 const HttpResponseInfo* response = trans->GetResponseInfo();
3283 EXPECT_FALSE(response == NULL);
3284 // The password prompt info should have been set in response->auth_challenge.
3285 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3286
3287 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3288 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3289 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3290
3291 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443292 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323293 EXPECT_EQ(ERR_IO_PENDING, rv);
3294 rv = callback3.WaitForResult();
3295 EXPECT_EQ(OK, rv);
3296 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3297
3298 response = trans->GetResponseInfo();
3299 EXPECT_FALSE(response == NULL);
3300
3301 // There is no challenge info, since the identity worked.
3302 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3303
3304 EXPECT_EQ(100, response->headers->GetContentLength());
3305
3306 // Empty the current queue.
3307 MessageLoop::current()->RunAllPending();
3308}
3309
[email protected]f9ee6b52008-11-08 06:46:233310// Test that previously tried username/passwords for a realm get re-used.
3311TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593312 SessionDependencies session_deps;
3313 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]f9ee6b52008-11-08 06:46:233314
3315 // Transaction 1: authenticate (foo, bar) on MyRealm1
3316 {
[email protected]5695b8c2009-09-30 21:36:433317 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233318
[email protected]1c773ea12009-04-28 19:58:423319 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233320 request.method = "GET";
3321 request.url = GURL("http://www.google.com/x/y/z");
3322 request.load_flags = 0;
3323
3324 MockWrite data_writes1[] = {
3325 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3326 "Host: www.google.com\r\n"
3327 "Connection: keep-alive\r\n\r\n"),
3328 };
3329
3330 MockRead data_reads1[] = {
3331 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3332 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3333 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423334 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233335 };
3336
3337 // Resend with authorization (username=foo, password=bar)
3338 MockWrite data_writes2[] = {
3339 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3340 "Host: www.google.com\r\n"
3341 "Connection: keep-alive\r\n"
3342 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3343 };
3344
3345 // Sever accepts the authorization.
3346 MockRead data_reads2[] = {
3347 MockRead("HTTP/1.0 200 OK\r\n"),
3348 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423349 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233350 };
3351
[email protected]31a2bfe2010-02-09 08:03:393352 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3353 data_writes1, arraysize(data_writes1));
3354 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3355 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593356 session_deps.socket_factory.AddSocketDataProvider(&data1);
3357 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233358
3359 TestCompletionCallback callback1;
3360
[email protected]5a1d7ca2010-04-28 20:12:273361 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423362 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233363
3364 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423365 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233366
[email protected]1c773ea12009-04-28 19:58:423367 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233368 EXPECT_FALSE(response == NULL);
3369
3370 // The password prompt info should have been set in
3371 // response->auth_challenge.
3372 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3373
[email protected]71e4573a2009-05-21 22:03:003374 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233375 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3376 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3377
3378 TestCompletionCallback callback2;
3379
[email protected]13c8a092010-07-29 06:15:443380 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423381 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233382
3383 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423384 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233385
3386 response = trans->GetResponseInfo();
3387 EXPECT_FALSE(response == NULL);
3388 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3389 EXPECT_EQ(100, response->headers->GetContentLength());
3390 }
3391
3392 // ------------------------------------------------------------------------
3393
3394 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3395 {
[email protected]5695b8c2009-09-30 21:36:433396 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233397
[email protected]1c773ea12009-04-28 19:58:423398 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233399 request.method = "GET";
3400 // Note that Transaction 1 was at /x/y/z, so this is in the same
3401 // protection space as MyRealm1.
3402 request.url = GURL("http://www.google.com/x/y/a/b");
3403 request.load_flags = 0;
3404
3405 MockWrite data_writes1[] = {
3406 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3407 "Host: www.google.com\r\n"
3408 "Connection: keep-alive\r\n"
3409 // Send preemptive authorization for MyRealm1
3410 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3411 };
3412
3413 // The server didn't like the preemptive authorization, and
3414 // challenges us for a different realm (MyRealm2).
3415 MockRead data_reads1[] = {
3416 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3417 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3418 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423419 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233420 };
3421
3422 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3423 MockWrite data_writes2[] = {
3424 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3425 "Host: www.google.com\r\n"
3426 "Connection: keep-alive\r\n"
3427 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3428 };
3429
3430 // Sever accepts the authorization.
3431 MockRead data_reads2[] = {
3432 MockRead("HTTP/1.0 200 OK\r\n"),
3433 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423434 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233435 };
3436
[email protected]31a2bfe2010-02-09 08:03:393437 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3438 data_writes1, arraysize(data_writes1));
3439 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3440 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593441 session_deps.socket_factory.AddSocketDataProvider(&data1);
3442 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233443
3444 TestCompletionCallback callback1;
3445
[email protected]5a1d7ca2010-04-28 20:12:273446 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423447 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233448
3449 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423450 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233451
[email protected]1c773ea12009-04-28 19:58:423452 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233453 EXPECT_FALSE(response == NULL);
3454
3455 // The password prompt info should have been set in
3456 // response->auth_challenge.
3457 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3458
[email protected]71e4573a2009-05-21 22:03:003459 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233460 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3461 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3462
3463 TestCompletionCallback callback2;
3464
[email protected]13c8a092010-07-29 06:15:443465 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423466 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233467
3468 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423469 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233470
3471 response = trans->GetResponseInfo();
3472 EXPECT_FALSE(response == NULL);
3473 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3474 EXPECT_EQ(100, response->headers->GetContentLength());
3475 }
3476
3477 // ------------------------------------------------------------------------
3478
3479 // Transaction 3: Resend a request in MyRealm's protection space --
3480 // succeed with preemptive authorization.
3481 {
[email protected]5695b8c2009-09-30 21:36:433482 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233483
[email protected]1c773ea12009-04-28 19:58:423484 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233485 request.method = "GET";
3486 request.url = GURL("http://www.google.com/x/y/z2");
3487 request.load_flags = 0;
3488
3489 MockWrite data_writes1[] = {
3490 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3491 "Host: www.google.com\r\n"
3492 "Connection: keep-alive\r\n"
3493 // The authorization for MyRealm1 gets sent preemptively
3494 // (since the url is in the same protection space)
3495 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3496 };
3497
3498 // Sever accepts the preemptive authorization
3499 MockRead data_reads1[] = {
3500 MockRead("HTTP/1.0 200 OK\r\n"),
3501 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423502 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233503 };
3504
[email protected]31a2bfe2010-02-09 08:03:393505 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3506 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593507 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233508
3509 TestCompletionCallback callback1;
3510
[email protected]5a1d7ca2010-04-28 20:12:273511 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423512 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233513
3514 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423515 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233516
[email protected]1c773ea12009-04-28 19:58:423517 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233518 EXPECT_FALSE(response == NULL);
3519
3520 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3521 EXPECT_EQ(100, response->headers->GetContentLength());
3522 }
3523
3524 // ------------------------------------------------------------------------
3525
3526 // Transaction 4: request another URL in MyRealm (however the
3527 // url is not known to belong to the protection space, so no pre-auth).
3528 {
[email protected]5695b8c2009-09-30 21:36:433529 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233530
[email protected]1c773ea12009-04-28 19:58:423531 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233532 request.method = "GET";
3533 request.url = GURL("http://www.google.com/x/1");
3534 request.load_flags = 0;
3535
3536 MockWrite data_writes1[] = {
3537 MockWrite("GET /x/1 HTTP/1.1\r\n"
3538 "Host: www.google.com\r\n"
3539 "Connection: keep-alive\r\n\r\n"),
3540 };
3541
3542 MockRead data_reads1[] = {
3543 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3544 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3545 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423546 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233547 };
3548
3549 // Resend with authorization from MyRealm's cache.
3550 MockWrite data_writes2[] = {
3551 MockWrite("GET /x/1 HTTP/1.1\r\n"
3552 "Host: www.google.com\r\n"
3553 "Connection: keep-alive\r\n"
3554 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3555 };
3556
3557 // Sever accepts the authorization.
3558 MockRead data_reads2[] = {
3559 MockRead("HTTP/1.0 200 OK\r\n"),
3560 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423561 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233562 };
3563
[email protected]31a2bfe2010-02-09 08:03:393564 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3565 data_writes1, arraysize(data_writes1));
3566 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3567 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593568 session_deps.socket_factory.AddSocketDataProvider(&data1);
3569 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233570
3571 TestCompletionCallback callback1;
3572
[email protected]5a1d7ca2010-04-28 20:12:273573 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423574 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233575
3576 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423577 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233578
[email protected]0757e7702009-03-27 04:00:223579 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3580 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443581 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423582 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223583 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423584 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223585 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3586
[email protected]1c773ea12009-04-28 19:58:423587 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233588 EXPECT_FALSE(response == NULL);
3589 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3590 EXPECT_EQ(100, response->headers->GetContentLength());
3591 }
3592
3593 // ------------------------------------------------------------------------
3594
3595 // Transaction 5: request a URL in MyRealm, but the server rejects the
3596 // cached identity. Should invalidate and re-prompt.
3597 {
[email protected]5695b8c2009-09-30 21:36:433598 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233599
[email protected]1c773ea12009-04-28 19:58:423600 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233601 request.method = "GET";
3602 request.url = GURL("http://www.google.com/p/q/t");
3603 request.load_flags = 0;
3604
3605 MockWrite data_writes1[] = {
3606 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3607 "Host: www.google.com\r\n"
3608 "Connection: keep-alive\r\n\r\n"),
3609 };
3610
3611 MockRead data_reads1[] = {
3612 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3613 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3614 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423615 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233616 };
3617
3618 // Resend with authorization from cache for MyRealm.
3619 MockWrite data_writes2[] = {
3620 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3621 "Host: www.google.com\r\n"
3622 "Connection: keep-alive\r\n"
3623 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3624 };
3625
3626 // Sever rejects the authorization.
3627 MockRead data_reads2[] = {
3628 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3629 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3630 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423631 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233632 };
3633
3634 // At this point we should prompt for new credentials for MyRealm.
3635 // Restart with username=foo3, password=foo4.
3636 MockWrite data_writes3[] = {
3637 MockWrite("GET /p/q/t HTTP/1.1\r\n"
3638 "Host: www.google.com\r\n"
3639 "Connection: keep-alive\r\n"
3640 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
3641 };
3642
3643 // Sever accepts the authorization.
3644 MockRead data_reads3[] = {
3645 MockRead("HTTP/1.0 200 OK\r\n"),
3646 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423647 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233648 };
3649
[email protected]31a2bfe2010-02-09 08:03:393650 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3651 data_writes1, arraysize(data_writes1));
3652 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3653 data_writes2, arraysize(data_writes2));
3654 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3655 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593656 session_deps.socket_factory.AddSocketDataProvider(&data1);
3657 session_deps.socket_factory.AddSocketDataProvider(&data2);
3658 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:233659
3660 TestCompletionCallback callback1;
3661
[email protected]5a1d7ca2010-04-28 20:12:273662 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423663 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233664
3665 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423666 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233667
[email protected]0757e7702009-03-27 04:00:223668 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3669 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443670 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423671 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223672 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423673 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223674 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3675
[email protected]1c773ea12009-04-28 19:58:423676 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233677 EXPECT_FALSE(response == NULL);
3678
3679 // The password prompt info should have been set in
3680 // response->auth_challenge.
3681 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3682
[email protected]71e4573a2009-05-21 22:03:003683 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233684 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3685 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3686
[email protected]0757e7702009-03-27 04:00:223687 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:233688
[email protected]13c8a092010-07-29 06:15:443689 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:423690 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233691
[email protected]0757e7702009-03-27 04:00:223692 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423693 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233694
3695 response = trans->GetResponseInfo();
3696 EXPECT_FALSE(response == NULL);
3697 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3698 EXPECT_EQ(100, response->headers->GetContentLength());
3699 }
3700}
[email protected]89ceba9a2009-03-21 03:46:063701
[email protected]3c32c5f2010-05-18 15:18:123702// Tests that nonce count increments when multiple auth attempts
3703// are started with the same nonce.
3704TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
3705 SessionDependencies session_deps;
3706 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
3707 HttpAuthHandlerDigest::SetFixedCnonce(true);
3708
3709 // Transaction 1: authenticate (foo, bar) on MyRealm1
3710 {
3711 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3712
3713 HttpRequestInfo request;
3714 request.method = "GET";
3715 request.url = GURL("http://www.google.com/x/y/z");
3716 request.load_flags = 0;
3717
3718 MockWrite data_writes1[] = {
3719 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3720 "Host: www.google.com\r\n"
3721 "Connection: keep-alive\r\n\r\n"),
3722 };
3723
3724 MockRead data_reads1[] = {
3725 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3726 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
3727 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
3728 MockRead(false, OK),
3729 };
3730
3731 // Resend with authorization (username=foo, password=bar)
3732 MockWrite data_writes2[] = {
3733 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3734 "Host: www.google.com\r\n"
3735 "Connection: keep-alive\r\n"
3736 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3737 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
3738 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
3739 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3740 };
3741
3742 // Sever accepts the authorization.
3743 MockRead data_reads2[] = {
3744 MockRead("HTTP/1.0 200 OK\r\n"),
3745 MockRead(false, OK),
3746 };
3747
3748 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3749 data_writes1, arraysize(data_writes1));
3750 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3751 data_writes2, arraysize(data_writes2));
3752 session_deps.socket_factory.AddSocketDataProvider(&data1);
3753 session_deps.socket_factory.AddSocketDataProvider(&data2);
3754
3755 TestCompletionCallback callback1;
3756
3757 int rv = trans->Start(&request, &callback1, BoundNetLog());
3758 EXPECT_EQ(ERR_IO_PENDING, rv);
3759
3760 rv = callback1.WaitForResult();
3761 EXPECT_EQ(OK, rv);
3762
3763 const HttpResponseInfo* response = trans->GetResponseInfo();
3764 ASSERT_FALSE(response == NULL);
3765
3766 // The password prompt info should have been set in
3767 // response->auth_challenge.
3768 ASSERT_FALSE(response->auth_challenge.get() == NULL);
3769
3770 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3771 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
3772 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
3773
3774 TestCompletionCallback callback2;
3775
[email protected]13c8a092010-07-29 06:15:443776 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:123777 EXPECT_EQ(ERR_IO_PENDING, rv);
3778
3779 rv = callback2.WaitForResult();
3780 EXPECT_EQ(OK, rv);
3781
3782 response = trans->GetResponseInfo();
3783 ASSERT_FALSE(response == NULL);
3784 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3785 }
3786
3787 // ------------------------------------------------------------------------
3788
3789 // Transaction 2: Request another resource in digestive's protection space.
3790 // This will preemptively add an Authorization header which should have an
3791 // "nc" value of 2 (as compared to 1 in the first use.
3792 {
3793 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3794
3795 HttpRequestInfo request;
3796 request.method = "GET";
3797 // Note that Transaction 1 was at /x/y/z, so this is in the same
3798 // protection space as digest.
3799 request.url = GURL("http://www.google.com/x/y/a/b");
3800 request.load_flags = 0;
3801
3802 MockWrite data_writes1[] = {
3803 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3804 "Host: www.google.com\r\n"
3805 "Connection: keep-alive\r\n"
3806 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
3807 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
3808 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
3809 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
3810 };
3811
3812 // Sever accepts the authorization.
3813 MockRead data_reads1[] = {
3814 MockRead("HTTP/1.0 200 OK\r\n"),
3815 MockRead("Content-Length: 100\r\n\r\n"),
3816 MockRead(false, OK),
3817 };
3818
3819 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3820 data_writes1, arraysize(data_writes1));
3821 session_deps.socket_factory.AddSocketDataProvider(&data1);
3822
3823 TestCompletionCallback callback1;
3824
3825 int rv = trans->Start(&request, &callback1, BoundNetLog());
3826 EXPECT_EQ(ERR_IO_PENDING, rv);
3827
3828 rv = callback1.WaitForResult();
3829 EXPECT_EQ(OK, rv);
3830
3831 const HttpResponseInfo* response = trans->GetResponseInfo();
3832 ASSERT_FALSE(response == NULL);
3833 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3834 }
3835}
3836
[email protected]89ceba9a2009-03-21 03:46:063837// Test the ResetStateForRestart() private method.
3838TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
3839 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:593840 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403841 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433842 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:063843
3844 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:063845 trans->read_buf_ = new IOBuffer(15);
3846 trans->read_buf_len_ = 15;
[email protected]0877e3d2009-10-17 22:29:573847 trans->request_headers_ = "Authorization: NTLM";
[email protected]89ceba9a2009-03-21 03:46:063848
3849 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:143850 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:573851 response->auth_challenge = new AuthChallengeInfo();
3852 response->ssl_info.cert_status = -15;
3853 response->response_time = base::Time::Now();
3854 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:063855
3856 { // Setup state for response_.vary_data
3857 HttpRequestInfo request;
3858 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
3859 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]0877e3d2009-10-17 22:29:573860 scoped_refptr<HttpResponseHeaders> headers = new HttpResponseHeaders(temp);
[email protected]8c76ae22010-04-20 22:15:433861 request.extra_headers.SetHeader("Foo", "1");
3862 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:573863 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:063864 }
3865
3866 // Cause the above state to be reset.
3867 trans->ResetStateForRestart();
3868
3869 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:073870 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:063871 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]0877e3d2009-10-17 22:29:573872 EXPECT_EQ(0U, trans->request_headers_.size());
3873 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3874 EXPECT_TRUE(response->headers.get() == NULL);
3875 EXPECT_EQ(false, response->was_cached);
3876 EXPECT_EQ(0, response->ssl_info.cert_status);
3877 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:063878}
3879
[email protected]bacff652009-03-31 17:50:333880// Test HTTPS connections to a site with a bad certificate
3881TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:593882 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403883 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433884 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333885
3886 HttpRequestInfo request;
3887 request.method = "GET";
3888 request.url = GURL("https://www.google.com/");
3889 request.load_flags = 0;
3890
3891 MockWrite data_writes[] = {
3892 MockWrite("GET / HTTP/1.1\r\n"
3893 "Host: www.google.com\r\n"
3894 "Connection: keep-alive\r\n\r\n"),
3895 };
3896
3897 MockRead data_reads[] = {
3898 MockRead("HTTP/1.0 200 OK\r\n"),
3899 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3900 MockRead("Content-Length: 100\r\n\r\n"),
3901 MockRead(false, OK),
3902 };
3903
[email protected]5ecc992a42009-11-11 01:41:593904 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:393905 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3906 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593907 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3908 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333909
[email protected]5ecc992a42009-11-11 01:41:593910 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3911 session_deps.socket_factory.AddSocketDataProvider(&data);
3912 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3913 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333914
3915 TestCompletionCallback callback;
3916
[email protected]5a1d7ca2010-04-28 20:12:273917 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333918 EXPECT_EQ(ERR_IO_PENDING, rv);
3919
3920 rv = callback.WaitForResult();
3921 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3922
3923 rv = trans->RestartIgnoringLastError(&callback);
3924 EXPECT_EQ(ERR_IO_PENDING, rv);
3925
3926 rv = callback.WaitForResult();
3927 EXPECT_EQ(OK, rv);
3928
3929 const HttpResponseInfo* response = trans->GetResponseInfo();
3930
3931 EXPECT_FALSE(response == NULL);
3932 EXPECT_EQ(100, response->headers->GetContentLength());
3933}
3934
3935// Test HTTPS connections to a site with a bad certificate, going through a
3936// proxy
3937TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]228ff742009-06-05 01:19:593938 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
[email protected]bacff652009-03-31 17:50:333939
3940 HttpRequestInfo request;
3941 request.method = "GET";
3942 request.url = GURL("https://www.google.com/");
3943 request.load_flags = 0;
3944
3945 MockWrite proxy_writes[] = {
3946 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453947 "Host: www.google.com\r\n"
3948 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333949 };
3950
3951 MockRead proxy_reads[] = {
3952 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423953 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:333954 };
3955
3956 MockWrite data_writes[] = {
3957 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453958 "Host: www.google.com\r\n"
3959 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:333960 MockWrite("GET / HTTP/1.1\r\n"
3961 "Host: www.google.com\r\n"
3962 "Connection: keep-alive\r\n\r\n"),
3963 };
3964
3965 MockRead data_reads[] = {
3966 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
3967 MockRead("HTTP/1.0 200 OK\r\n"),
3968 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
3969 MockRead("Content-Length: 100\r\n\r\n"),
3970 MockRead(false, OK),
3971 };
3972
[email protected]31a2bfe2010-02-09 08:03:393973 StaticSocketDataProvider ssl_bad_certificate(
3974 proxy_reads, arraysize(proxy_reads),
3975 proxy_writes, arraysize(proxy_writes));
3976 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3977 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:593978 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
3979 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:333980
[email protected]5ecc992a42009-11-11 01:41:593981 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
3982 session_deps.socket_factory.AddSocketDataProvider(&data);
3983 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
3984 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:333985
3986 TestCompletionCallback callback;
3987
3988 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:593989 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:333990
[email protected]d207a5f2009-06-04 05:28:403991 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433992 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:333993
[email protected]5a1d7ca2010-04-28 20:12:273994 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:333995 EXPECT_EQ(ERR_IO_PENDING, rv);
3996
3997 rv = callback.WaitForResult();
3998 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
3999
4000 rv = trans->RestartIgnoringLastError(&callback);
4001 EXPECT_EQ(ERR_IO_PENDING, rv);
4002
4003 rv = callback.WaitForResult();
4004 EXPECT_EQ(OK, rv);
4005
4006 const HttpResponseInfo* response = trans->GetResponseInfo();
4007
4008 EXPECT_FALSE(response == NULL);
4009 EXPECT_EQ(100, response->headers->GetContentLength());
4010 }
4011}
4012
[email protected]2df19bb2010-08-25 20:13:464013
4014// Test HTTPS connections to a site, going through an HTTPS proxy
4015TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
4016 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
4017
4018 HttpRequestInfo request;
4019 request.method = "GET";
4020 request.url = GURL("https://www.google.com/");
4021 request.load_flags = 0;
4022
4023 MockWrite data_writes[] = {
4024 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4025 "Host: www.google.com\r\n"
4026 "Proxy-Connection: keep-alive\r\n\r\n"),
4027 MockWrite("GET / HTTP/1.1\r\n"
4028 "Host: www.google.com\r\n"
4029 "Connection: keep-alive\r\n\r\n"),
4030 };
4031
4032 MockRead data_reads[] = {
4033 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4034 MockRead("HTTP/1.1 200 OK\r\n"),
4035 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4036 MockRead("Content-Length: 100\r\n\r\n"),
4037 MockRead(false, OK),
4038 };
4039
4040 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4041 data_writes, arraysize(data_writes));
4042 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4043 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4044
4045 session_deps.socket_factory.AddSocketDataProvider(&data);
4046 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4047 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4048
4049 TestCompletionCallback callback;
4050
4051 scoped_ptr<HttpTransaction> trans(
4052 new HttpNetworkTransaction(CreateSession(&session_deps)));
4053
4054 int rv = trans->Start(&request, &callback, BoundNetLog());
4055 EXPECT_EQ(ERR_IO_PENDING, rv);
4056
4057 rv = callback.WaitForResult();
4058 EXPECT_EQ(OK, rv);
4059 const HttpResponseInfo* response = trans->GetResponseInfo();
4060
4061 ASSERT_FALSE(response == NULL);
4062
4063 EXPECT_TRUE(response->headers->IsKeepAlive());
4064 EXPECT_EQ(200, response->headers->response_code());
4065 EXPECT_EQ(100, response->headers->GetContentLength());
4066 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4067}
4068
4069// Test HTTPS connections to a site with a bad certificate, going through an
4070// HTTPS proxy
4071TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
4072 SessionDependencies session_deps(CreateFixedProxyService("https://proxy:70"));
4073
4074 HttpRequestInfo request;
4075 request.method = "GET";
4076 request.url = GURL("https://www.google.com/");
4077 request.load_flags = 0;
4078
4079 // Attempt to fetch the URL from a server with a bad cert
4080 MockWrite bad_cert_writes[] = {
4081 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4082 "Host: www.google.com\r\n"
4083 "Proxy-Connection: keep-alive\r\n\r\n"),
4084 };
4085
4086 MockRead bad_cert_reads[] = {
4087 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4088 MockRead(false, OK)
4089 };
4090
4091 // Attempt to fetch the URL with a good cert
4092 MockWrite good_data_writes[] = {
4093 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4094 "Host: www.google.com\r\n"
4095 "Proxy-Connection: keep-alive\r\n\r\n"),
4096 MockWrite("GET / HTTP/1.1\r\n"
4097 "Host: www.google.com\r\n"
4098 "Connection: keep-alive\r\n\r\n"),
4099 };
4100
4101 MockRead good_cert_reads[] = {
4102 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4103 MockRead("HTTP/1.0 200 OK\r\n"),
4104 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4105 MockRead("Content-Length: 100\r\n\r\n"),
4106 MockRead(false, OK),
4107 };
4108
4109 StaticSocketDataProvider ssl_bad_certificate(
4110 bad_cert_reads, arraysize(bad_cert_reads),
4111 bad_cert_writes, arraysize(bad_cert_writes));
4112 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4113 good_data_writes, arraysize(good_data_writes));
4114 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4115 SSLSocketDataProvider ssl(true, OK);
4116
4117 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4118 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4119 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4120 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4121
4122 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4123 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4124 session_deps.socket_factory.AddSocketDataProvider(&data);
4125 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4126
4127 TestCompletionCallback callback;
4128
4129 scoped_ptr<HttpTransaction> trans(
4130 new HttpNetworkTransaction(CreateSession(&session_deps)));
4131
4132 int rv = trans->Start(&request, &callback, BoundNetLog());
4133 EXPECT_EQ(ERR_IO_PENDING, rv);
4134
4135 rv = callback.WaitForResult();
4136 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4137
4138 rv = trans->RestartIgnoringLastError(&callback);
4139 EXPECT_EQ(ERR_IO_PENDING, rv);
4140
4141 rv = callback.WaitForResult();
4142 EXPECT_EQ(OK, rv);
4143
4144 const HttpResponseInfo* response = trans->GetResponseInfo();
4145
4146 EXPECT_FALSE(response == NULL);
4147 EXPECT_EQ(100, response->headers->GetContentLength());
4148}
4149
[email protected]1c773ea12009-04-28 19:58:424150TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:594151 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404152 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434153 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424154
4155 HttpRequestInfo request;
4156 request.method = "GET";
4157 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434158 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4159 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424160
4161 MockWrite data_writes[] = {
4162 MockWrite("GET / HTTP/1.1\r\n"
4163 "Host: www.google.com\r\n"
4164 "Connection: keep-alive\r\n"
4165 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4166 };
4167
4168 // Lastly, the server responds with the actual content.
4169 MockRead data_reads[] = {
4170 MockRead("HTTP/1.0 200 OK\r\n"),
4171 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4172 MockRead("Content-Length: 100\r\n\r\n"),
4173 MockRead(false, OK),
4174 };
4175
[email protected]31a2bfe2010-02-09 08:03:394176 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4177 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594178 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424179
4180 TestCompletionCallback callback;
4181
[email protected]5a1d7ca2010-04-28 20:12:274182 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424183 EXPECT_EQ(ERR_IO_PENDING, rv);
4184
4185 rv = callback.WaitForResult();
4186 EXPECT_EQ(OK, rv);
4187}
4188
[email protected]da81f132010-08-18 23:39:294189TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
4190 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
4191 scoped_ptr<HttpTransaction> trans(
4192 new HttpNetworkTransaction(CreateSession(&session_deps)));
4193
4194 HttpRequestInfo request;
4195 request.method = "GET";
4196 request.url = GURL("https://www.google.com/");
4197 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4198 "Chromium Ultra Awesome X Edition");
4199
4200 MockWrite data_writes[] = {
4201 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4202 "Host: www.google.com\r\n"
4203 "Proxy-Connection: keep-alive\r\n"
4204 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4205 };
4206 MockRead data_reads[] = {
4207 // Return an error, so the transaction stops here (this test isn't
4208 // interested in the rest).
4209 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4210 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4211 MockRead("Proxy-Connection: close\r\n\r\n"),
4212 };
4213
4214 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4215 data_writes, arraysize(data_writes));
4216 session_deps.socket_factory.AddSocketDataProvider(&data);
4217
4218 TestCompletionCallback callback;
4219
4220 int rv = trans->Start(&request, &callback, BoundNetLog());
4221 EXPECT_EQ(ERR_IO_PENDING, rv);
4222
4223 rv = callback.WaitForResult();
4224 EXPECT_EQ(OK, rv);
4225}
4226
[email protected]1c773ea12009-04-28 19:58:424227TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594228 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404229 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434230 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424231
4232 HttpRequestInfo request;
4233 request.method = "GET";
4234 request.url = GURL("http://www.google.com/");
4235 request.load_flags = 0;
4236 request.referrer = GURL("http://the.previous.site.com/");
4237
4238 MockWrite data_writes[] = {
4239 MockWrite("GET / HTTP/1.1\r\n"
4240 "Host: www.google.com\r\n"
4241 "Connection: keep-alive\r\n"
4242 "Referer: http://the.previous.site.com/\r\n\r\n"),
4243 };
4244
4245 // Lastly, the server responds with the actual content.
4246 MockRead data_reads[] = {
4247 MockRead("HTTP/1.0 200 OK\r\n"),
4248 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4249 MockRead("Content-Length: 100\r\n\r\n"),
4250 MockRead(false, OK),
4251 };
4252
[email protected]31a2bfe2010-02-09 08:03:394253 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4254 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594255 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424256
4257 TestCompletionCallback callback;
4258
[email protected]5a1d7ca2010-04-28 20:12:274259 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424260 EXPECT_EQ(ERR_IO_PENDING, rv);
4261
4262 rv = callback.WaitForResult();
4263 EXPECT_EQ(OK, rv);
4264}
4265
4266TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594267 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404268 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434269 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424270
4271 HttpRequestInfo request;
4272 request.method = "POST";
4273 request.url = GURL("http://www.google.com/");
4274
4275 MockWrite data_writes[] = {
4276 MockWrite("POST / HTTP/1.1\r\n"
4277 "Host: www.google.com\r\n"
4278 "Connection: keep-alive\r\n"
4279 "Content-Length: 0\r\n\r\n"),
4280 };
4281
4282 // Lastly, the server responds with the actual content.
4283 MockRead data_reads[] = {
4284 MockRead("HTTP/1.0 200 OK\r\n"),
4285 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4286 MockRead("Content-Length: 100\r\n\r\n"),
4287 MockRead(false, OK),
4288 };
4289
[email protected]31a2bfe2010-02-09 08:03:394290 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4291 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594292 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424293
4294 TestCompletionCallback callback;
4295
[email protected]5a1d7ca2010-04-28 20:12:274296 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424297 EXPECT_EQ(ERR_IO_PENDING, rv);
4298
4299 rv = callback.WaitForResult();
4300 EXPECT_EQ(OK, rv);
4301}
4302
4303TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594304 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404305 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434306 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424307
4308 HttpRequestInfo request;
4309 request.method = "PUT";
4310 request.url = GURL("http://www.google.com/");
4311
4312 MockWrite data_writes[] = {
4313 MockWrite("PUT / HTTP/1.1\r\n"
4314 "Host: www.google.com\r\n"
4315 "Connection: keep-alive\r\n"
4316 "Content-Length: 0\r\n\r\n"),
4317 };
4318
4319 // Lastly, the server responds with the actual content.
4320 MockRead data_reads[] = {
4321 MockRead("HTTP/1.0 200 OK\r\n"),
4322 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4323 MockRead("Content-Length: 100\r\n\r\n"),
4324 MockRead(false, OK),
4325 };
4326
[email protected]31a2bfe2010-02-09 08:03:394327 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4328 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594329 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424330
4331 TestCompletionCallback callback;
4332
[email protected]5a1d7ca2010-04-28 20:12:274333 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424334 EXPECT_EQ(ERR_IO_PENDING, rv);
4335
4336 rv = callback.WaitForResult();
4337 EXPECT_EQ(OK, rv);
4338}
4339
4340TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594341 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404342 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434343 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424344
4345 HttpRequestInfo request;
4346 request.method = "HEAD";
4347 request.url = GURL("http://www.google.com/");
4348
4349 MockWrite data_writes[] = {
4350 MockWrite("HEAD / HTTP/1.1\r\n"
4351 "Host: www.google.com\r\n"
4352 "Connection: keep-alive\r\n"
4353 "Content-Length: 0\r\n\r\n"),
4354 };
4355
4356 // Lastly, the server responds with the actual content.
4357 MockRead data_reads[] = {
4358 MockRead("HTTP/1.0 200 OK\r\n"),
4359 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4360 MockRead("Content-Length: 100\r\n\r\n"),
4361 MockRead(false, OK),
4362 };
4363
[email protected]31a2bfe2010-02-09 08:03:394364 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4365 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594366 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424367
4368 TestCompletionCallback callback;
4369
[email protected]5a1d7ca2010-04-28 20:12:274370 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424371 EXPECT_EQ(ERR_IO_PENDING, rv);
4372
4373 rv = callback.WaitForResult();
4374 EXPECT_EQ(OK, rv);
4375}
4376
4377TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:594378 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404379 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434380 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424381
4382 HttpRequestInfo request;
4383 request.method = "GET";
4384 request.url = GURL("http://www.google.com/");
4385 request.load_flags = LOAD_BYPASS_CACHE;
4386
4387 MockWrite data_writes[] = {
4388 MockWrite("GET / HTTP/1.1\r\n"
4389 "Host: www.google.com\r\n"
4390 "Connection: keep-alive\r\n"
4391 "Pragma: no-cache\r\n"
4392 "Cache-Control: no-cache\r\n\r\n"),
4393 };
4394
4395 // Lastly, the server responds with the actual content.
4396 MockRead data_reads[] = {
4397 MockRead("HTTP/1.0 200 OK\r\n"),
4398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4399 MockRead("Content-Length: 100\r\n\r\n"),
4400 MockRead(false, OK),
4401 };
4402
[email protected]31a2bfe2010-02-09 08:03:394403 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4404 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594405 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424406
4407 TestCompletionCallback callback;
4408
[email protected]5a1d7ca2010-04-28 20:12:274409 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424410 EXPECT_EQ(ERR_IO_PENDING, rv);
4411
4412 rv = callback.WaitForResult();
4413 EXPECT_EQ(OK, rv);
4414}
4415
4416TEST_F(HttpNetworkTransactionTest,
4417 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:594418 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404419 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434420 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424421
4422 HttpRequestInfo request;
4423 request.method = "GET";
4424 request.url = GURL("http://www.google.com/");
4425 request.load_flags = LOAD_VALIDATE_CACHE;
4426
4427 MockWrite data_writes[] = {
4428 MockWrite("GET / HTTP/1.1\r\n"
4429 "Host: www.google.com\r\n"
4430 "Connection: keep-alive\r\n"
4431 "Cache-Control: max-age=0\r\n\r\n"),
4432 };
4433
4434 // Lastly, the server responds with the actual content.
4435 MockRead data_reads[] = {
4436 MockRead("HTTP/1.0 200 OK\r\n"),
4437 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4438 MockRead("Content-Length: 100\r\n\r\n"),
4439 MockRead(false, OK),
4440 };
4441
[email protected]31a2bfe2010-02-09 08:03:394442 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4443 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594444 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424445
4446 TestCompletionCallback callback;
4447
[email protected]5a1d7ca2010-04-28 20:12:274448 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424449 EXPECT_EQ(ERR_IO_PENDING, rv);
4450
4451 rv = callback.WaitForResult();
4452 EXPECT_EQ(OK, rv);
4453}
4454
4455TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:594456 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404457 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434458 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424459
4460 HttpRequestInfo request;
4461 request.method = "GET";
4462 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434463 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:424464
4465 MockWrite data_writes[] = {
4466 MockWrite("GET / HTTP/1.1\r\n"
4467 "Host: www.google.com\r\n"
4468 "Connection: keep-alive\r\n"
4469 "FooHeader: Bar\r\n\r\n"),
4470 };
4471
4472 // Lastly, the server responds with the actual content.
4473 MockRead data_reads[] = {
4474 MockRead("HTTP/1.0 200 OK\r\n"),
4475 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4476 MockRead("Content-Length: 100\r\n\r\n"),
4477 MockRead(false, OK),
4478 };
4479
[email protected]31a2bfe2010-02-09 08:03:394480 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4481 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594482 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424483
4484 TestCompletionCallback callback;
4485
[email protected]5a1d7ca2010-04-28 20:12:274486 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424487 EXPECT_EQ(ERR_IO_PENDING, rv);
4488
4489 rv = callback.WaitForResult();
4490 EXPECT_EQ(OK, rv);
4491}
4492
[email protected]270c6412010-03-29 22:02:474493TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
4494 SessionDependencies session_deps;
4495 scoped_ptr<HttpTransaction> trans(
4496 new HttpNetworkTransaction(CreateSession(&session_deps)));
4497
4498 HttpRequestInfo request;
4499 request.method = "GET";
4500 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434501 request.extra_headers.SetHeader("referer", "www.foo.com");
4502 request.extra_headers.SetHeader("hEllo", "Kitty");
4503 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:474504
4505 MockWrite data_writes[] = {
4506 MockWrite("GET / HTTP/1.1\r\n"
4507 "Host: www.google.com\r\n"
4508 "Connection: keep-alive\r\n"
4509 "hEllo: Kitty\r\n"
4510 "FoO: bar\r\n\r\n"),
4511 };
4512
4513 // Lastly, the server responds with the actual content.
4514 MockRead data_reads[] = {
4515 MockRead("HTTP/1.0 200 OK\r\n"),
4516 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4517 MockRead("Content-Length: 100\r\n\r\n"),
4518 MockRead(false, OK),
4519 };
4520
4521 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4522 data_writes, arraysize(data_writes));
4523 session_deps.socket_factory.AddSocketDataProvider(&data);
4524
4525 TestCompletionCallback callback;
4526
[email protected]5a1d7ca2010-04-28 20:12:274527 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:474528 EXPECT_EQ(ERR_IO_PENDING, rv);
4529
4530 rv = callback.WaitForResult();
4531 EXPECT_EQ(OK, rv);
4532}
4533
[email protected]3cd17242009-06-23 02:59:024534TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094535 SessionDependencies session_deps(
4536 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024537
4538 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434539 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024540
4541 HttpRequestInfo request;
4542 request.method = "GET";
4543 request.url = GURL("http://www.google.com/");
4544 request.load_flags = 0;
4545
4546 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
4547 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4548
4549 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354550 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024551 MockWrite("GET / HTTP/1.1\r\n"
4552 "Host: www.google.com\r\n"
4553 "Connection: keep-alive\r\n\r\n")
4554 };
4555
4556 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:594557 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:024558 MockRead("HTTP/1.0 200 OK\r\n"),
4559 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4560 MockRead("Payload"),
4561 MockRead(false, OK)
4562 };
4563
[email protected]31a2bfe2010-02-09 08:03:394564 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4565 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594566 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024567
4568 TestCompletionCallback callback;
4569
[email protected]5a1d7ca2010-04-28 20:12:274570 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024571 EXPECT_EQ(ERR_IO_PENDING, rv);
4572
4573 rv = callback.WaitForResult();
4574 EXPECT_EQ(OK, rv);
4575
4576 const HttpResponseInfo* response = trans->GetResponseInfo();
4577 EXPECT_FALSE(response == NULL);
4578
4579 std::string response_text;
4580 rv = ReadTransaction(trans.get(), &response_text);
4581 EXPECT_EQ(OK, rv);
4582 EXPECT_EQ("Payload", response_text);
4583}
4584
4585TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094586 SessionDependencies session_deps(
4587 CreateFixedProxyService("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:024588
4589 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434590 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:024591
4592 HttpRequestInfo request;
4593 request.method = "GET";
4594 request.url = GURL("https://www.google.com/");
4595 request.load_flags = 0;
4596
4597 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
4598 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
4599
4600 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:354601 MockWrite(true, reinterpret_cast<char*>(write_buffer),
4602 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:024603 MockWrite("GET / HTTP/1.1\r\n"
4604 "Host: www.google.com\r\n"
4605 "Connection: keep-alive\r\n\r\n")
4606 };
4607
4608 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:354609 MockWrite(true, reinterpret_cast<char*>(read_buffer),
4610 arraysize(read_buffer)),
4611 MockRead("HTTP/1.0 200 OK\r\n"),
4612 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4613 MockRead("Payload"),
4614 MockRead(false, OK)
4615 };
4616
[email protected]31a2bfe2010-02-09 08:03:394617 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4618 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594619 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354620
[email protected]5ecc992a42009-11-11 01:41:594621 SSLSocketDataProvider ssl(true, OK);
4622 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:354623
4624 TestCompletionCallback callback;
4625
[email protected]5a1d7ca2010-04-28 20:12:274626 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354627 EXPECT_EQ(ERR_IO_PENDING, rv);
4628
4629 rv = callback.WaitForResult();
4630 EXPECT_EQ(OK, rv);
4631
4632 const HttpResponseInfo* response = trans->GetResponseInfo();
4633 EXPECT_FALSE(response == NULL);
4634
4635 std::string response_text;
4636 rv = ReadTransaction(trans.get(), &response_text);
4637 EXPECT_EQ(OK, rv);
4638 EXPECT_EQ("Payload", response_text);
4639}
4640
4641TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:094642 SessionDependencies session_deps(
4643 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354644
4645 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434646 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354647
4648 HttpRequestInfo request;
4649 request.method = "GET";
4650 request.url = GURL("http://www.google.com/");
4651 request.load_flags = 0;
4652
4653 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4654 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374655 const char kSOCKS5OkRequest[] = {
4656 0x05, // Version
4657 0x01, // Command (CONNECT)
4658 0x00, // Reserved.
4659 0x03, // Address type (DOMAINNAME).
4660 0x0E, // Length of domain (14)
4661 // Domain string:
4662 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4663 0x00, 0x50, // 16-bit port (80)
4664 };
[email protected]e0c27be2009-07-15 13:09:354665 const char kSOCKS5OkResponse[] =
4666 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
4667
4668 MockWrite data_writes[] = {
4669 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4670 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
4671 MockWrite("GET / HTTP/1.1\r\n"
4672 "Host: www.google.com\r\n"
4673 "Connection: keep-alive\r\n\r\n")
4674 };
4675
4676 MockRead data_reads[] = {
4677 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4678 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
4679 MockRead("HTTP/1.0 200 OK\r\n"),
4680 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4681 MockRead("Payload"),
4682 MockRead(false, OK)
4683 };
4684
[email protected]31a2bfe2010-02-09 08:03:394685 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4686 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594687 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:354688
4689 TestCompletionCallback callback;
4690
[email protected]5a1d7ca2010-04-28 20:12:274691 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:354692 EXPECT_EQ(ERR_IO_PENDING, rv);
4693
4694 rv = callback.WaitForResult();
4695 EXPECT_EQ(OK, rv);
4696
4697 const HttpResponseInfo* response = trans->GetResponseInfo();
4698 EXPECT_FALSE(response == NULL);
4699
4700 std::string response_text;
4701 rv = ReadTransaction(trans.get(), &response_text);
4702 EXPECT_EQ(OK, rv);
4703 EXPECT_EQ("Payload", response_text);
4704}
4705
4706TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:094707 SessionDependencies session_deps(
4708 CreateFixedProxyService("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:354709
4710 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434711 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:354712
4713 HttpRequestInfo request;
4714 request.method = "GET";
4715 request.url = GURL("https://www.google.com/");
4716 request.load_flags = 0;
4717
4718 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
4719 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:374720 const unsigned char kSOCKS5OkRequest[] = {
4721 0x05, // Version
4722 0x01, // Command (CONNECT)
4723 0x00, // Reserved.
4724 0x03, // Address type (DOMAINNAME).
4725 0x0E, // Length of domain (14)
4726 // Domain string:
4727 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
4728 0x01, 0xBB, // 16-bit port (443)
4729 };
4730
[email protected]e0c27be2009-07-15 13:09:354731 const char kSOCKS5OkResponse[] =
4732 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
4733
4734 MockWrite data_writes[] = {
4735 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
4736 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
4737 arraysize(kSOCKS5OkRequest)),
4738 MockWrite("GET / HTTP/1.1\r\n"
4739 "Host: www.google.com\r\n"
4740 "Connection: keep-alive\r\n\r\n")
4741 };
4742
4743 MockRead data_reads[] = {
4744 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
4745 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:024746 MockRead("HTTP/1.0 200 OK\r\n"),
4747 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
4748 MockRead("Payload"),
4749 MockRead(false, OK)
4750 };
4751
[email protected]31a2bfe2010-02-09 08:03:394752 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4753 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594754 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:024755
[email protected]5ecc992a42009-11-11 01:41:594756 SSLSocketDataProvider ssl(true, OK);
4757 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:024758
4759 TestCompletionCallback callback;
4760
[email protected]5a1d7ca2010-04-28 20:12:274761 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:024762 EXPECT_EQ(ERR_IO_PENDING, rv);
4763
4764 rv = callback.WaitForResult();
4765 EXPECT_EQ(OK, rv);
4766
4767 const HttpResponseInfo* response = trans->GetResponseInfo();
4768 EXPECT_FALSE(response == NULL);
4769
4770 std::string response_text;
4771 rv = ReadTransaction(trans.get(), &response_text);
4772 EXPECT_EQ(OK, rv);
4773 EXPECT_EQ("Payload", response_text);
4774}
4775
[email protected]04e5be32009-06-26 20:00:314776// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:064777
4778struct GroupNameTest {
4779 std::string proxy_server;
4780 std::string url;
4781 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:184782 bool ssl;
[email protected]2d731a32010-04-29 01:04:064783};
4784
4785scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
4786 const std::string& proxy_server) {
4787 SessionDependencies session_deps(CreateFixedProxyService(proxy_server));
4788 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4789
4790 HttpAlternateProtocols* alternate_protocols =
4791 session->mutable_alternate_protocols();
4792 alternate_protocols->SetAlternateProtocolFor(
4793 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:354794 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:064795
4796 return session;
4797}
4798
4799int GroupNameTransactionHelper(
4800 const std::string& url,
4801 const scoped_refptr<HttpNetworkSession>& session) {
4802 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4803
4804 HttpRequestInfo request;
4805 request.method = "GET";
4806 request.url = GURL(url);
4807 request.load_flags = 0;
4808
4809 TestCompletionCallback callback;
4810
4811 // We do not complete this request, the dtor will clean the transaction up.
4812 return trans->Start(&request, &callback, BoundNetLog());
4813}
4814
4815TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
4816 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:314817 {
[email protected]2d731a32010-04-29 01:04:064818 "", // unused
[email protected]04e5be32009-06-26 20:00:314819 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:544820 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184821 false,
[email protected]2ff8b312010-04-26 22:20:544822 },
4823 {
[email protected]2d731a32010-04-29 01:04:064824 "", // unused
[email protected]2ff8b312010-04-26 22:20:544825 "http://[2001:1418:13:1::25]/direct",
4826 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:184827 false,
[email protected]04e5be32009-06-26 20:00:314828 },
[email protected]04e5be32009-06-26 20:00:314829
4830 // SSL Tests
4831 {
[email protected]2d731a32010-04-29 01:04:064832 "", // unused
[email protected]04e5be32009-06-26 20:00:314833 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:024834 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184835 true,
[email protected]04e5be32009-06-26 20:00:314836 },
4837 {
[email protected]2d731a32010-04-29 01:04:064838 "", // unused
4839 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:024840 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:184841 true,
[email protected]04e5be32009-06-26 20:00:314842 },
4843 {
[email protected]2d731a32010-04-29 01:04:064844 "", // unused
[email protected]2ff8b312010-04-26 22:20:544845 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024846 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184847 true,
[email protected]2ff8b312010-04-26 22:20:544848 },
[email protected]2d731a32010-04-29 01:04:064849 };
[email protected]2ff8b312010-04-26 22:20:544850
[email protected]8e6441ca2010-08-19 05:56:384851 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064852
4853 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4854 scoped_refptr<HttpNetworkSession> session(
4855 SetupSessionForGroupNameTests(tests[i].proxy_server));
4856
4857 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:134858 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
4859 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:064860 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:134861 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
4862 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:184863 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064864
4865 EXPECT_EQ(ERR_IO_PENDING,
4866 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184867 if (tests[i].ssl)
4868 EXPECT_EQ(tests[i].expected_group_name,
4869 ssl_conn_pool->last_group_name_received());
4870 else
4871 EXPECT_EQ(tests[i].expected_group_name,
4872 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064873 }
4874
[email protected]8e6441ca2010-08-19 05:56:384875 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064876}
4877
4878TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
4879 const GroupNameTest tests[] = {
4880 {
4881 "http_proxy",
4882 "http://www.google.com/http_proxy_normal",
4883 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184884 false,
[email protected]2d731a32010-04-29 01:04:064885 },
4886
4887 // SSL Tests
4888 {
4889 "http_proxy",
4890 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:024891 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184892 true,
[email protected]2d731a32010-04-29 01:04:064893 },
4894
[email protected]9faeded92010-04-29 20:03:054895 {
4896 "http_proxy",
4897 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024898 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184899 true,
[email protected]9faeded92010-04-29 20:03:054900 },
[email protected]2d731a32010-04-29 01:04:064901 };
4902
[email protected]8e6441ca2010-08-19 05:56:384903 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:064904
4905 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
4906 scoped_refptr<HttpNetworkSession> session(
4907 SetupSessionForGroupNameTests(tests[i].proxy_server));
4908
4909 HttpNetworkSessionPeer peer(session);
4910
[email protected]e60e47a2010-07-14 03:37:184911 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:134912 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
4913 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184914 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:134915 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
4916 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184917 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:064918
4919 EXPECT_EQ(ERR_IO_PENDING,
4920 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184921 if (tests[i].ssl)
4922 EXPECT_EQ(tests[i].expected_group_name,
4923 ssl_conn_pool->last_group_name_received());
4924 else
4925 EXPECT_EQ(tests[i].expected_group_name,
4926 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:064927 }
4928
[email protected]8e6441ca2010-08-19 05:56:384929 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:064930}
4931
4932TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
4933 const GroupNameTest tests[] = {
4934 {
4935 "socks4://socks_proxy:1080",
4936 "http://www.google.com/socks4_direct",
4937 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184938 false,
[email protected]2d731a32010-04-29 01:04:064939 },
4940 {
4941 "socks5://socks_proxy:1080",
4942 "http://www.google.com/socks5_direct",
4943 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:184944 false,
[email protected]2d731a32010-04-29 01:04:064945 },
4946
4947 // SSL Tests
4948 {
4949 "socks4://socks_proxy:1080",
4950 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:024951 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184952 true,
[email protected]2d731a32010-04-29 01:04:064953 },
4954 {
4955 "socks5://socks_proxy:1080",
4956 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:024957 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:184958 true,
[email protected]2d731a32010-04-29 01:04:064959 },
4960
[email protected]9faeded92010-04-29 20:03:054961 {
4962 "socks4://socks_proxy:1080",
4963 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:024964 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:184965 true,
[email protected]9faeded92010-04-29 20:03:054966 },
[email protected]04e5be32009-06-26 20:00:314967 };
4968
[email protected]8e6441ca2010-08-19 05:56:384969 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:544970
[email protected]04e5be32009-06-26 20:00:314971 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:064972 scoped_refptr<HttpNetworkSession> session(
4973 SetupSessionForGroupNameTests(tests[i].proxy_server));
4974 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:314975
[email protected]e60e47a2010-07-14 03:37:184976 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:134977 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
4978 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184979 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:134980 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
4981 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:184982 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:314983
[email protected]5695b8c2009-09-30 21:36:434984 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:314985
[email protected]2d731a32010-04-29 01:04:064986 EXPECT_EQ(ERR_IO_PENDING,
4987 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:184988 if (tests[i].ssl)
4989 EXPECT_EQ(tests[i].expected_group_name,
4990 ssl_conn_pool->last_group_name_received());
4991 else
4992 EXPECT_EQ(tests[i].expected_group_name,
4993 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:314994 }
[email protected]2ff8b312010-04-26 22:20:544995
[email protected]8e6441ca2010-08-19 05:56:384996 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:314997}
4998
[email protected]9172a982009-06-06 00:30:254999TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:545000 SessionDependencies session_deps(
5001 CreateFixedProxyService("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325002
[email protected]69719062010-01-05 20:09:215003 // This simulates failure resolving all hostnames; that means we will fail
5004 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325005 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5006
[email protected]9172a982009-06-06 00:30:255007 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435008 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255009
5010 HttpRequestInfo request;
5011 request.method = "GET";
5012 request.url = GURL("http://www.google.com/");
5013
5014 TestCompletionCallback callback;
5015
[email protected]5a1d7ca2010-04-28 20:12:275016 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255017 EXPECT_EQ(ERR_IO_PENDING, rv);
5018
[email protected]9172a982009-06-06 00:30:255019 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015020 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255021}
5022
[email protected]f3e6c1e2009-06-15 20:52:125023// Host resolution observer used by
5024// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5025// resovle requests are issued with a referrer of |expected_referrer|.
5026class ResolutionReferrerObserver : public HostResolver::Observer {
5027 public:
5028 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5029 : expected_referrer_(expected_referrer),
5030 called_start_with_referrer_(false),
5031 called_finish_with_referrer_(false) {
5032 }
5033
5034 virtual void OnStartResolution(int id,
5035 const HostResolver::RequestInfo& info) {
5036 if (info.referrer() == expected_referrer_)
5037 called_start_with_referrer_ = true;
5038 }
5039
5040 virtual void OnFinishResolutionWithStatus(
5041 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5042 if (info.referrer() == expected_referrer_)
5043 called_finish_with_referrer_ = true;
5044 }
5045
[email protected]eb255d32009-06-17 02:11:035046 virtual void OnCancelResolution(int id,
5047 const HostResolver::RequestInfo& info ) {
5048 FAIL() << "Should not be cancelling any requests!";
5049 }
5050
[email protected]f3e6c1e2009-06-15 20:52:125051 bool did_complete_with_expected_referrer() const {
5052 return called_start_with_referrer_ && called_finish_with_referrer_;
5053 }
5054
5055 private:
5056 GURL expected_referrer_;
5057 bool called_start_with_referrer_;
5058 bool called_finish_with_referrer_;
5059
5060 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5061};
5062
5063// Make sure that when HostResolver::Resolve() is invoked, it passes through
5064// the "referrer". This is depended on by the DNS prefetch observer.
5065TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5066 GURL referrer = GURL("http://expected-referrer/");
5067 EXPECT_TRUE(referrer.is_valid());
5068 ResolutionReferrerObserver resolution_observer(referrer);
5069
5070 SessionDependencies session_deps;
5071 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435072 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125073
5074 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145075 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125076
5077 // Connect up a mock socket which will fail when reading.
5078 MockRead data_reads[] = {
5079 MockRead(false, ERR_FAILED),
5080 };
[email protected]31a2bfe2010-02-09 08:03:395081 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595082 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125083
5084 // Issue a request, containing an HTTP referrer.
5085 HttpRequestInfo request;
5086 request.method = "GET";
5087 request.referrer = referrer;
5088 request.url = GURL("http://www.google.com/");
5089
5090 // Run the request until it fails reading from the socket.
5091 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275092 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125093 EXPECT_EQ(ERR_IO_PENDING, rv);
5094 rv = callback.WaitForResult();
5095 EXPECT_EQ(ERR_FAILED, rv);
5096
5097 // Check that the host resolution observer saw |referrer|.
5098 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5099}
5100
[email protected]685af592010-05-11 19:31:245101// Base test to make sure that when the load flags for a request specify to
5102// bypass the cache, the DNS cache is not used.
5103void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285104 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325105
[email protected]a2c2fb92009-07-18 07:31:045106 // Select a host resolver that does caching.
5107 session_deps.host_resolver = new MockCachingHostResolver;
[email protected]b59ff372009-07-15 22:04:325108
[email protected]3b9cca42009-06-16 01:08:285109 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435110 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285111
5112 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5113 // a synchronous lookup.)
5114 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145115 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105116 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275117 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285118 EXPECT_EQ(OK, rv);
5119
5120 // Verify that it was added to host cache, by doing a subsequent async lookup
5121 // and confirming it completes synchronously.
5122 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465123 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105124 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275125 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325126 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285127
5128 // Inject a failure the next time that "www.google.com" is resolved. This way
5129 // we can tell if the next lookup hit the cache, or the "network".
5130 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325131 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285132
5133 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5134 // first read -- this won't be reached as the host resolution will fail first.
5135 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395136 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595137 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285138
5139 // Issue a request, asking to bypass the cache(s).
5140 HttpRequestInfo request;
5141 request.method = "GET";
[email protected]685af592010-05-11 19:31:245142 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285143 request.url = GURL("http://www.google.com/");
5144
5145 // Run the request.
5146 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275147 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285148 ASSERT_EQ(ERR_IO_PENDING, rv);
5149 rv = callback.WaitForResult();
5150
5151 // If we bypassed the cache, we would have gotten a failure while resolving
5152 // "www.google.com".
5153 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5154}
5155
[email protected]685af592010-05-11 19:31:245156// There are multiple load flags that should trigger the host cache bypass.
5157// Test each in isolation:
5158TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5159 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5160}
5161
5162TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5163 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5164}
5165
5166TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5167 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5168}
5169
[email protected]0877e3d2009-10-17 22:29:575170// Make sure we can handle an error when writing the request.
5171TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5172 SessionDependencies session_deps;
5173 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5174
5175 HttpRequestInfo request;
5176 request.method = "GET";
5177 request.url = GURL("http://www.foo.com/");
5178 request.load_flags = 0;
5179
5180 MockWrite write_failure[] = {
5181 MockWrite(true, ERR_CONNECTION_RESET),
5182 };
[email protected]31a2bfe2010-02-09 08:03:395183 StaticSocketDataProvider data(NULL, 0,
5184 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595185 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575186
5187 TestCompletionCallback callback;
5188
5189 scoped_ptr<HttpTransaction> trans(
5190 new HttpNetworkTransaction(CreateSession(&session_deps)));
5191
[email protected]5a1d7ca2010-04-28 20:12:275192 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575193 EXPECT_EQ(ERR_IO_PENDING, rv);
5194
5195 rv = callback.WaitForResult();
5196 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5197}
5198
5199// Check that a connection closed after the start of the headers finishes ok.
5200TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5201 SessionDependencies session_deps;
5202 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
5203
5204 HttpRequestInfo request;
5205 request.method = "GET";
5206 request.url = GURL("http://www.foo.com/");
5207 request.load_flags = 0;
5208
5209 MockRead data_reads[] = {
5210 MockRead("HTTP/1."),
5211 MockRead(false, OK),
5212 };
5213
[email protected]31a2bfe2010-02-09 08:03:395214 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595215 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575216
5217 TestCompletionCallback callback;
5218
5219 scoped_ptr<HttpTransaction> trans(
5220 new HttpNetworkTransaction(CreateSession(&session_deps)));
5221
[email protected]5a1d7ca2010-04-28 20:12:275222 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575223 EXPECT_EQ(ERR_IO_PENDING, rv);
5224
5225 rv = callback.WaitForResult();
5226 EXPECT_EQ(OK, rv);
5227
5228 const HttpResponseInfo* response = trans->GetResponseInfo();
5229 EXPECT_TRUE(response != NULL);
5230
5231 EXPECT_TRUE(response->headers != NULL);
5232 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5233
5234 std::string response_data;
5235 rv = ReadTransaction(trans.get(), &response_data);
5236 EXPECT_EQ(OK, rv);
5237 EXPECT_EQ("", response_data);
5238}
5239
5240// Make sure that a dropped connection while draining the body for auth
5241// restart does the right thing.
5242TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5243 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:505244 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
[email protected]0877e3d2009-10-17 22:29:575245
5246 HttpRequestInfo request;
5247 request.method = "GET";
5248 request.url = GURL("http://www.google.com/");
5249 request.load_flags = 0;
5250
5251 MockWrite data_writes1[] = {
5252 MockWrite("GET / HTTP/1.1\r\n"
5253 "Host: www.google.com\r\n"
5254 "Connection: keep-alive\r\n\r\n"),
5255 };
5256
5257 MockRead data_reads1[] = {
5258 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5259 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5260 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5261 MockRead("Content-Length: 14\r\n\r\n"),
5262 MockRead("Unauth"),
5263 MockRead(true, ERR_CONNECTION_RESET),
5264 };
5265
[email protected]31a2bfe2010-02-09 08:03:395266 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5267 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595268 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575269
5270 // After calling trans->RestartWithAuth(), this is the request we should
5271 // be issuing -- the final header line contains the credentials.
5272 MockWrite data_writes2[] = {
5273 MockWrite("GET / HTTP/1.1\r\n"
5274 "Host: www.google.com\r\n"
5275 "Connection: keep-alive\r\n"
5276 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5277 };
5278
5279 // Lastly, the server responds with the actual content.
5280 MockRead data_reads2[] = {
5281 MockRead("HTTP/1.1 200 OK\r\n"),
5282 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5283 MockRead("Content-Length: 100\r\n\r\n"),
5284 MockRead(false, OK),
5285 };
5286
[email protected]31a2bfe2010-02-09 08:03:395287 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5288 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595289 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575290
5291 TestCompletionCallback callback1;
5292
[email protected]0b0bf032010-09-21 18:08:505293 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5294
[email protected]5a1d7ca2010-04-28 20:12:275295 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575296 EXPECT_EQ(ERR_IO_PENDING, rv);
5297
5298 rv = callback1.WaitForResult();
5299 EXPECT_EQ(OK, rv);
5300
5301 const HttpResponseInfo* response = trans->GetResponseInfo();
5302 EXPECT_FALSE(response == NULL);
5303
5304 // The password prompt info should have been set in response->auth_challenge.
5305 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5306
5307 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5308 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5309 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5310
5311 TestCompletionCallback callback2;
5312
[email protected]13c8a092010-07-29 06:15:445313 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575314 EXPECT_EQ(ERR_IO_PENDING, rv);
5315
5316 rv = callback2.WaitForResult();
5317 EXPECT_EQ(OK, rv);
5318
5319 response = trans->GetResponseInfo();
5320 EXPECT_FALSE(response == NULL);
5321 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5322 EXPECT_EQ(100, response->headers->GetContentLength());
5323}
5324
5325// Test HTTPS connections going through a proxy that sends extra data.
5326TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
5327 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
5328
5329 HttpRequestInfo request;
5330 request.method = "GET";
5331 request.url = GURL("https://www.google.com/");
5332 request.load_flags = 0;
5333
5334 MockRead proxy_reads[] = {
5335 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5336 MockRead(false, OK)
5337 };
5338
[email protected]31a2bfe2010-02-09 08:03:395339 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595340 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575341
[email protected]5ecc992a42009-11-11 01:41:595342 session_deps.socket_factory.AddSocketDataProvider(&data);
5343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575344
5345 TestCompletionCallback callback;
5346
5347 session_deps.socket_factory.ResetNextMockIndexes();
5348
5349 scoped_ptr<HttpTransaction> trans(
5350 new HttpNetworkTransaction(CreateSession(&session_deps)));
5351
[email protected]5a1d7ca2010-04-28 20:12:275352 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575353 EXPECT_EQ(ERR_IO_PENDING, rv);
5354
5355 rv = callback.WaitForResult();
5356 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5357}
5358
[email protected]e22e1362009-11-23 21:31:125359TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465360 SessionDependencies session_deps;
5361 scoped_ptr<HttpTransaction> trans(
5362 new HttpNetworkTransaction(CreateSession(&session_deps)));
5363
5364 HttpRequestInfo request;
5365 request.method = "GET";
5366 request.url = GURL("http://www.google.com/");
5367 request.load_flags = 0;
5368
[email protected]e22e1362009-11-23 21:31:125369 MockRead data_reads[] = {
5370 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5371 MockRead(false, OK),
5372 };
[email protected]9492e4a2010-02-24 00:58:465373
5374 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5375 session_deps.socket_factory.AddSocketDataProvider(&data);
5376
5377 TestCompletionCallback callback;
5378
[email protected]5a1d7ca2010-04-28 20:12:275379 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465380 EXPECT_EQ(ERR_IO_PENDING, rv);
5381
5382 EXPECT_EQ(OK, callback.WaitForResult());
5383
5384 const HttpResponseInfo* response = trans->GetResponseInfo();
5385 EXPECT_TRUE(response != NULL);
5386
5387 EXPECT_TRUE(response->headers != NULL);
5388 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5389
5390 std::string response_data;
5391 rv = ReadTransaction(trans.get(), &response_data);
5392 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:125393}
5394
[email protected]95d88ffe2010-02-04 21:25:335395TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
5396 SessionDependencies session_deps;
5397 scoped_ptr<HttpTransaction> trans(
5398 new HttpNetworkTransaction(CreateSession(&session_deps)));
5399
5400 HttpRequestInfo request;
5401 request.method = "POST";
5402 request.url = GURL("http://www.google.com/upload");
5403 request.upload_data = new UploadData;
5404 request.load_flags = 0;
5405
5406 FilePath temp_file_path;
5407 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
5408 const uint64 kFakeSize = 100000; // file is actually blank
5409
5410 std::vector<UploadData::Element> elements;
5411 UploadData::Element element;
5412 element.SetToFilePath(temp_file_path);
5413 element.SetContentLength(kFakeSize);
5414 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535415 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:335416 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
5417
5418 MockRead data_reads[] = {
5419 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5420 MockRead("hello world"),
5421 MockRead(false, OK),
5422 };
[email protected]31a2bfe2010-02-09 08:03:395423 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:335424 session_deps.socket_factory.AddSocketDataProvider(&data);
5425
5426 TestCompletionCallback callback;
5427
[email protected]5a1d7ca2010-04-28 20:12:275428 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:335429 EXPECT_EQ(ERR_IO_PENDING, rv);
5430
5431 rv = callback.WaitForResult();
5432 EXPECT_EQ(OK, rv);
5433
5434 const HttpResponseInfo* response = trans->GetResponseInfo();
5435 EXPECT_TRUE(response != NULL);
5436
5437 EXPECT_TRUE(response->headers != NULL);
5438 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5439
5440 std::string response_data;
5441 rv = ReadTransaction(trans.get(), &response_data);
5442 EXPECT_EQ(OK, rv);
5443 EXPECT_EQ("hello world", response_data);
5444
5445 file_util::Delete(temp_file_path, false);
5446}
5447
[email protected]6624b4622010-03-29 19:58:365448TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
5449 // If we try to upload an unreadable file, the network stack should report
5450 // the file size as zero and upload zero bytes for that file.
5451 SessionDependencies session_deps;
5452 scoped_ptr<HttpTransaction> trans(
5453 new HttpNetworkTransaction(CreateSession(&session_deps)));
5454
5455 FilePath temp_file;
5456 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5457 std::string temp_file_content("Unreadable file.");
5458 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
5459 temp_file_content.length()));
5460 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5461
5462 HttpRequestInfo request;
5463 request.method = "POST";
5464 request.url = GURL("http://www.google.com/upload");
5465 request.upload_data = new UploadData;
5466 request.load_flags = 0;
5467
5468 std::vector<UploadData::Element> elements;
5469 UploadData::Element element;
5470 element.SetToFilePath(temp_file);
5471 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535472 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365473
5474 MockRead data_reads[] = {
5475 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
5476 MockRead(false, OK),
5477 };
5478 MockWrite data_writes[] = {
5479 MockWrite("POST /upload HTTP/1.1\r\n"
5480 "Host: www.google.com\r\n"
5481 "Connection: keep-alive\r\n"
5482 "Content-Length: 0\r\n\r\n"),
5483 MockWrite(false, OK),
5484 };
5485 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5486 arraysize(data_writes));
5487 session_deps.socket_factory.AddSocketDataProvider(&data);
5488
5489 TestCompletionCallback callback;
5490
[email protected]5a1d7ca2010-04-28 20:12:275491 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365492 EXPECT_EQ(ERR_IO_PENDING, rv);
5493
5494 rv = callback.WaitForResult();
5495 EXPECT_EQ(OK, rv);
5496
5497 const HttpResponseInfo* response = trans->GetResponseInfo();
5498 EXPECT_TRUE(response != NULL);
5499 EXPECT_TRUE(response->headers != NULL);
5500 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5501
5502 file_util::Delete(temp_file, false);
5503}
5504
5505TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
5506 SessionDependencies session_deps;
5507 scoped_ptr<HttpTransaction> trans(
5508 new HttpNetworkTransaction(CreateSession(&session_deps)));
5509
5510 FilePath temp_file;
5511 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
5512 std::string temp_file_contents("Unreadable file.");
5513 std::string unreadable_contents(temp_file_contents.length(), '\0');
5514 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
5515 temp_file_contents.length()));
5516
5517 HttpRequestInfo request;
5518 request.method = "POST";
5519 request.url = GURL("http://www.google.com/upload");
5520 request.upload_data = new UploadData;
5521 request.load_flags = 0;
5522
5523 std::vector<UploadData::Element> elements;
5524 UploadData::Element element;
5525 element.SetToFilePath(temp_file);
5526 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:535527 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:365528
5529 MockRead data_reads[] = {
5530 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5531 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5532 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
5533
5534 MockRead("HTTP/1.1 200 OK\r\n"),
5535 MockRead("Content-Length: 0\r\n\r\n"),
5536 MockRead(false, OK),
5537 };
5538 MockWrite data_writes[] = {
5539 MockWrite("POST /upload HTTP/1.1\r\n"
5540 "Host: www.google.com\r\n"
5541 "Connection: keep-alive\r\n"
5542 "Content-Length: 16\r\n\r\n"),
5543 MockWrite(false, temp_file_contents.c_str()),
5544
5545 MockWrite("POST /upload HTTP/1.1\r\n"
5546 "Host: www.google.com\r\n"
5547 "Connection: keep-alive\r\n"
5548 "Content-Length: 16\r\n"
5549 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5550 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
5551 MockWrite(false, OK),
5552 };
5553 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
5554 arraysize(data_writes));
5555 session_deps.socket_factory.AddSocketDataProvider(&data);
5556
5557 TestCompletionCallback callback1;
5558
[email protected]5a1d7ca2010-04-28 20:12:275559 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:365560 EXPECT_EQ(ERR_IO_PENDING, rv);
5561
5562 rv = callback1.WaitForResult();
5563 EXPECT_EQ(OK, rv);
5564
5565 const HttpResponseInfo* response = trans->GetResponseInfo();
5566 EXPECT_TRUE(response != NULL);
5567 EXPECT_TRUE(response->headers != NULL);
5568 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
5569
5570 // The password prompt info should have been set in response->auth_challenge.
5571 EXPECT_TRUE(response->auth_challenge.get() != NULL);
5572 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5573 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5574 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5575
5576 // Now make the file unreadable and try again.
5577 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
5578
5579 TestCompletionCallback callback2;
5580
[email protected]13c8a092010-07-29 06:15:445581 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:365582 EXPECT_EQ(ERR_IO_PENDING, rv);
5583
5584 rv = callback2.WaitForResult();
5585 EXPECT_EQ(OK, rv);
5586
5587 response = trans->GetResponseInfo();
5588 EXPECT_TRUE(response != NULL);
5589 EXPECT_TRUE(response->headers != NULL);
5590 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5591 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5592
5593 file_util::Delete(temp_file, false);
5594}
5595
[email protected]aeefc9e82010-02-19 16:18:275596// Tests that changes to Auth realms are treated like auth rejections.
5597TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
5598 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:275599
5600 HttpRequestInfo request;
5601 request.method = "GET";
5602 request.url = GURL("http://www.google.com/");
5603 request.load_flags = 0;
5604
5605 // First transaction will request a resource and receive a Basic challenge
5606 // with realm="first_realm".
5607 MockWrite data_writes1[] = {
5608 MockWrite("GET / HTTP/1.1\r\n"
5609 "Host: www.google.com\r\n"
5610 "Connection: keep-alive\r\n"
5611 "\r\n"),
5612 };
5613 MockRead data_reads1[] = {
5614 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5615 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5616 "\r\n"),
5617 };
5618
5619 // After calling trans->RestartWithAuth(), provide an Authentication header
5620 // for first_realm. The server will reject and provide a challenge with
5621 // second_realm.
5622 MockWrite data_writes2[] = {
5623 MockWrite("GET / HTTP/1.1\r\n"
5624 "Host: www.google.com\r\n"
5625 "Connection: keep-alive\r\n"
5626 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
5627 "\r\n"),
5628 };
5629 MockRead data_reads2[] = {
5630 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5631 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
5632 "\r\n"),
5633 };
5634
5635 // This again fails, and goes back to first_realm. Make sure that the
5636 // entry is removed from cache.
5637 MockWrite data_writes3[] = {
5638 MockWrite("GET / HTTP/1.1\r\n"
5639 "Host: www.google.com\r\n"
5640 "Connection: keep-alive\r\n"
5641 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
5642 "\r\n"),
5643 };
5644 MockRead data_reads3[] = {
5645 MockRead("HTTP/1.1 401 Unauthorized\r\n"
5646 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
5647 "\r\n"),
5648 };
5649
5650 // Try one last time (with the correct password) and get the resource.
5651 MockWrite data_writes4[] = {
5652 MockWrite("GET / HTTP/1.1\r\n"
5653 "Host: www.google.com\r\n"
5654 "Connection: keep-alive\r\n"
5655 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
5656 "\r\n"),
5657 };
5658 MockRead data_reads4[] = {
5659 MockRead("HTTP/1.1 200 OK\r\n"
5660 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:505661 "Content-Length: 5\r\n"
5662 "\r\n"
5663 "hello"),
[email protected]aeefc9e82010-02-19 16:18:275664 };
5665
5666 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5667 data_writes1, arraysize(data_writes1));
5668 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5669 data_writes2, arraysize(data_writes2));
5670 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
5671 data_writes3, arraysize(data_writes3));
5672 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
5673 data_writes4, arraysize(data_writes4));
5674 session_deps.socket_factory.AddSocketDataProvider(&data1);
5675 session_deps.socket_factory.AddSocketDataProvider(&data2);
5676 session_deps.socket_factory.AddSocketDataProvider(&data3);
5677 session_deps.socket_factory.AddSocketDataProvider(&data4);
5678
5679 TestCompletionCallback callback1;
5680
[email protected]0b0bf032010-09-21 18:08:505681 scoped_ptr<HttpTransaction> trans(
5682 new HttpNetworkTransaction(CreateSession(&session_deps)));
5683
[email protected]aeefc9e82010-02-19 16:18:275684 // Issue the first request with Authorize headers. There should be a
5685 // password prompt for first_realm waiting to be filled in after the
5686 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:275687 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:275688 EXPECT_EQ(ERR_IO_PENDING, rv);
5689 rv = callback1.WaitForResult();
5690 EXPECT_EQ(OK, rv);
5691 const HttpResponseInfo* response = trans->GetResponseInfo();
5692 ASSERT_FALSE(response == NULL);
5693 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5694 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5695 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5696 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5697
5698 // Issue the second request with an incorrect password. There should be a
5699 // password prompt for second_realm waiting to be filled in after the
5700 // transaction completes.
5701 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:445702 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:275703 EXPECT_EQ(ERR_IO_PENDING, rv);
5704 rv = callback2.WaitForResult();
5705 EXPECT_EQ(OK, rv);
5706 response = trans->GetResponseInfo();
5707 ASSERT_FALSE(response == NULL);
5708 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5709 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5710 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
5711 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5712
5713 // Issue the third request with another incorrect password. There should be
5714 // a password prompt for first_realm waiting to be filled in. If the password
5715 // prompt is not present, it indicates that the HttpAuthCacheEntry for
5716 // first_realm was not correctly removed.
5717 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:445718 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:275719 EXPECT_EQ(ERR_IO_PENDING, rv);
5720 rv = callback3.WaitForResult();
5721 EXPECT_EQ(OK, rv);
5722 response = trans->GetResponseInfo();
5723 ASSERT_FALSE(response == NULL);
5724 ASSERT_FALSE(response->auth_challenge.get() == NULL);
5725 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5726 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
5727 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5728
5729 // Issue the fourth request with the correct password and username.
5730 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:445731 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:275732 EXPECT_EQ(ERR_IO_PENDING, rv);
5733 rv = callback4.WaitForResult();
5734 EXPECT_EQ(OK, rv);
5735 response = trans->GetResponseInfo();
5736 ASSERT_FALSE(response == NULL);
5737 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5738}
5739
[email protected]564b4912010-03-09 16:30:425740TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:385741 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
5742 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:425743
[email protected]564b4912010-03-09 16:30:425744 SessionDependencies session_deps;
5745
5746 MockRead data_reads[] = {
5747 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355748 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:425749 MockRead("hello world"),
5750 MockRead(false, OK),
5751 };
5752
5753 HttpRequestInfo request;
5754 request.method = "GET";
5755 request.url = GURL("http://www.google.com/");
5756 request.load_flags = 0;
5757
5758 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5759
5760 session_deps.socket_factory.AddSocketDataProvider(&data);
5761
5762 TestCompletionCallback callback;
5763
5764 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5765 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5766
[email protected]5a1d7ca2010-04-28 20:12:275767 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425768 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:535769
[email protected]2fbaecf22010-07-22 22:20:355770 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425771 const HttpAlternateProtocols& alternate_protocols =
5772 session->alternate_protocols();
5773 EXPECT_FALSE(
5774 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5775
5776 EXPECT_EQ(OK, callback.WaitForResult());
5777
5778 const HttpResponseInfo* response = trans->GetResponseInfo();
5779 ASSERT_TRUE(response != NULL);
5780 ASSERT_TRUE(response->headers != NULL);
5781 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:535782 EXPECT_FALSE(response->was_fetched_via_spdy);
5783 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:575784 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:425785
5786 std::string response_data;
5787 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5788 EXPECT_EQ("hello world", response_data);
5789
5790 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
5791 const HttpAlternateProtocols::PortProtocolPair alternate =
5792 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
5793 HttpAlternateProtocols::PortProtocolPair expected_alternate;
5794 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:355795 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:425796 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:425797
[email protected]8e6441ca2010-08-19 05:56:385798 HttpStreamFactory::set_use_alternate_protocols(false);
5799 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:425800}
5801
5802TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:385803 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:425804 SessionDependencies session_deps;
5805
5806 HttpRequestInfo request;
5807 request.method = "GET";
5808 request.url = GURL("http://www.google.com/");
5809 request.load_flags = 0;
5810
5811 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
5812 StaticSocketDataProvider first_data;
5813 first_data.set_connect_data(mock_connect);
5814 session_deps.socket_factory.AddSocketDataProvider(&first_data);
5815
5816 MockRead data_reads[] = {
5817 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5818 MockRead("hello world"),
5819 MockRead(true, OK),
5820 };
5821 StaticSocketDataProvider second_data(
5822 data_reads, arraysize(data_reads), NULL, 0);
5823 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5824
5825 // TODO(willchan): Delete this extra data provider. It's necessary due to a
5826 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
5827 // http://crbug.com/37454.
5828 session_deps.socket_factory.AddSocketDataProvider(&second_data);
5829
5830 TestCompletionCallback callback;
5831
5832 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5833
[email protected]2fbaecf22010-07-22 22:20:355834 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425835 HttpAlternateProtocols* alternate_protocols =
5836 session->mutable_alternate_protocols();
5837 alternate_protocols->SetAlternateProtocolFor(
5838 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:355839 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425840
5841 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5842
[email protected]5a1d7ca2010-04-28 20:12:275843 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425844 EXPECT_EQ(ERR_IO_PENDING, rv);
5845 EXPECT_EQ(OK, callback.WaitForResult());
5846
5847 const HttpResponseInfo* response = trans->GetResponseInfo();
5848 ASSERT_TRUE(response != NULL);
5849 ASSERT_TRUE(response->headers != NULL);
5850 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5851
5852 std::string response_data;
5853 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5854 EXPECT_EQ("hello world", response_data);
5855
5856 ASSERT_TRUE(
5857 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
5858 const HttpAlternateProtocols::PortProtocolPair alternate =
5859 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
5860 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:385861 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:425862}
5863
5864// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
5865// says that it does SPDY, but it just does the TLS handshake, but the NPN
5866// response does not indicate SPDY, so we just do standard HTTPS over the port.
5867// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
5868// on the original port.
[email protected]a2cb8122010-03-10 17:22:425869// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
5870// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:535871//
[email protected]a2cb8122010-03-10 17:22:425872// HttpRequestInfo request;
5873// request.method = "GET";
5874// request.url = GURL("http://www.google.com/");
5875// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:535876//
[email protected]a2cb8122010-03-10 17:22:425877// MockRead data_reads[] = {
5878// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5879// MockRead("hello world"),
5880// MockRead(true, OK),
5881// };
5882// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5883// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:535884//
[email protected]a2cb8122010-03-10 17:22:425885// SSLSocketDataProvider ssl(true, OK);
5886// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:535887//
[email protected]a2cb8122010-03-10 17:22:425888// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:535889//
[email protected]a2cb8122010-03-10 17:22:425890// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:535891//
[email protected]a2cb8122010-03-10 17:22:425892// HostPortPair http_host_port_pair;
5893// http_host_port_pair.host = "www.google.com";
5894// http_host_port_pair.port = 80;
5895// HttpAlternateProtocols* alternate_protocols =
5896// session->mutable_alternate_protocols();
5897// alternate_protocols->SetAlternateProtocolFor(
5898// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:065899// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:535900//
[email protected]a2cb8122010-03-10 17:22:425901// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:535902//
[email protected]5a1d7ca2010-04-28 20:12:275903// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:425904// EXPECT_EQ(ERR_IO_PENDING, rv);
5905// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:535906//
[email protected]a2cb8122010-03-10 17:22:425907// const HttpResponseInfo* response = trans->GetResponseInfo();
5908// ASSERT_TRUE(response != NULL);
5909// ASSERT_TRUE(response->headers != NULL);
5910// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:535911//
[email protected]a2cb8122010-03-10 17:22:425912// std::string response_data;
5913// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5914// EXPECT_EQ("hello world", response_data);
5915// }
5916
5917TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:385918 HttpStreamFactory::set_use_alternate_protocols(true);
5919 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:425920 SessionDependencies session_deps;
5921
5922 HttpRequestInfo request;
5923 request.method = "GET";
5924 request.url = GURL("http://www.google.com/");
5925 request.load_flags = 0;
5926
[email protected]a2cb8122010-03-10 17:22:425927 StaticSocketDataProvider first_tcp_connect;
5928 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
5929
5930 SSLSocketDataProvider ssl(true, OK);
5931 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5932
[email protected]564b4912010-03-09 16:30:425933 MockRead data_reads[] = {
5934 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
5935 MockRead("hello world"),
5936 MockRead(true, OK),
5937 };
[email protected]a2cb8122010-03-10 17:22:425938 StaticSocketDataProvider fallback_data(
5939 data_reads, arraysize(data_reads), NULL, 0);
5940 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:425941
5942 TestCompletionCallback callback;
5943
5944 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5945
[email protected]2fbaecf22010-07-22 22:20:355946 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:425947 HttpAlternateProtocols* alternate_protocols =
5948 session->mutable_alternate_protocols();
5949 alternate_protocols->SetAlternateProtocolFor(
5950 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:355951 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:425952
5953 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5954
[email protected]5a1d7ca2010-04-28 20:12:275955 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:425956 EXPECT_EQ(ERR_IO_PENDING, rv);
5957 EXPECT_EQ(OK, callback.WaitForResult());
5958
5959 const HttpResponseInfo* response = trans->GetResponseInfo();
5960 ASSERT_TRUE(response != NULL);
5961 ASSERT_TRUE(response->headers != NULL);
5962 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
5963
5964 std::string response_data;
5965 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
5966 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:385967 HttpStreamFactory::set_next_protos("");
5968 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:545969}
5970
5971TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:385972 HttpStreamFactory::set_use_alternate_protocols(true);
5973 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:545974 SessionDependencies session_deps;
5975
5976 HttpRequestInfo request;
5977 request.method = "GET";
5978 request.url = GURL("http://www.google.com/");
5979 request.load_flags = 0;
5980
5981 MockRead data_reads[] = {
5982 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:355983 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:545984 MockRead("hello world"),
5985 MockRead(true, OK),
5986 };
5987
5988 StaticSocketDataProvider first_transaction(
5989 data_reads, arraysize(data_reads), NULL, 0);
5990 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
5991
5992 SSLSocketDataProvider ssl(true, OK);
5993 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:355994 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:535995 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:545996 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
5997
[email protected]2bd93022010-07-17 00:58:445998 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:135999 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546000
[email protected]2bd93022010-07-17 00:58:446001 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6002 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546003 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136004 CreateMockRead(*resp),
6005 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546006 MockRead(true, 0, 0),
6007 };
6008
6009 scoped_refptr<DelayedSocketData> spdy_data(
6010 new DelayedSocketData(
6011 1, // wait for one write to finish before reading.
6012 spdy_reads, arraysize(spdy_reads),
6013 spdy_writes, arraysize(spdy_writes)));
6014 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6015
6016 TestCompletionCallback callback;
6017
6018 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6019 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6020
[email protected]5a1d7ca2010-04-28 20:12:276021 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546022 EXPECT_EQ(ERR_IO_PENDING, rv);
6023 EXPECT_EQ(OK, callback.WaitForResult());
6024
6025 const HttpResponseInfo* response = trans->GetResponseInfo();
6026 ASSERT_TRUE(response != NULL);
6027 ASSERT_TRUE(response->headers != NULL);
6028 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6029
6030 std::string response_data;
6031 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6032 EXPECT_EQ("hello world", response_data);
6033
6034 trans.reset(new HttpNetworkTransaction(session));
6035
[email protected]5a1d7ca2010-04-28 20:12:276036 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546037 EXPECT_EQ(ERR_IO_PENDING, rv);
6038 EXPECT_EQ(OK, callback.WaitForResult());
6039
6040 response = trans->GetResponseInfo();
6041 ASSERT_TRUE(response != NULL);
6042 ASSERT_TRUE(response->headers != NULL);
6043 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536044 EXPECT_TRUE(response->was_fetched_via_spdy);
6045 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576046 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546047
6048 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6049 EXPECT_EQ("hello!", response_data);
6050
[email protected]8e6441ca2010-08-19 05:56:386051 HttpStreamFactory::set_next_protos("");
6052 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546053}
6054
[email protected]631f1322010-04-30 17:59:116055class CapturingProxyResolver : public ProxyResolver {
6056 public:
6057 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6058 virtual ~CapturingProxyResolver() {}
6059
6060 virtual int GetProxyForURL(const GURL& url,
6061 ProxyInfo* results,
6062 CompletionCallback* callback,
6063 RequestHandle* request,
6064 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406065 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6066 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426067 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116068 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426069 return OK;
[email protected]631f1322010-04-30 17:59:116070 }
6071
6072 virtual void CancelRequest(RequestHandle request) {
6073 NOTREACHED();
6074 }
6075
[email protected]24476402010-07-20 20:55:176076 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116077 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426078 return OK;
[email protected]631f1322010-04-30 17:59:116079 }
6080
[email protected]24476402010-07-20 20:55:176081 const std::vector<GURL>& resolved() const { return resolved_; }
6082
6083 private:
[email protected]631f1322010-04-30 17:59:116084 std::vector<GURL> resolved_;
6085
6086 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6087};
6088
[email protected]631f1322010-04-30 17:59:116089TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386090 HttpStreamFactory::set_use_alternate_protocols(true);
6091 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116092
6093 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426094 proxy_config.set_auto_detect(true);
6095 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116096
[email protected]631f1322010-04-30 17:59:116097 CapturingProxyResolver* capturing_proxy_resolver =
6098 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386099 SessionDependencies session_deps(new ProxyService(
6100 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6101 NULL));
[email protected]631f1322010-04-30 17:59:116102
6103 HttpRequestInfo request;
6104 request.method = "GET";
6105 request.url = GURL("http://www.google.com/");
6106 request.load_flags = 0;
6107
6108 MockRead data_reads[] = {
6109 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356110 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116111 MockRead("hello world"),
6112 MockRead(true, OK),
6113 };
6114
6115 StaticSocketDataProvider first_transaction(
6116 data_reads, arraysize(data_reads), NULL, 0);
6117 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6118
6119 SSLSocketDataProvider ssl(true, OK);
6120 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356121 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536122 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116123 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6124
[email protected]2bd93022010-07-17 00:58:446125 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116126 MockWrite spdy_writes[] = {
6127 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6128 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426129 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136130 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116131 };
6132
[email protected]d911f1b2010-05-05 22:39:426133 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6134
[email protected]2bd93022010-07-17 00:58:446135 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6136 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116137 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426138 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136139 CreateMockRead(*resp.get(), 4), // 2, 4
6140 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426141 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116142 };
6143
[email protected]d911f1b2010-05-05 22:39:426144 scoped_refptr<OrderedSocketData> spdy_data(
6145 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116146 spdy_reads, arraysize(spdy_reads),
6147 spdy_writes, arraysize(spdy_writes)));
6148 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6149
6150 TestCompletionCallback callback;
6151
6152 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6153 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6154
6155 int rv = trans->Start(&request, &callback, BoundNetLog());
6156 EXPECT_EQ(ERR_IO_PENDING, rv);
6157 EXPECT_EQ(OK, callback.WaitForResult());
6158
6159 const HttpResponseInfo* response = trans->GetResponseInfo();
6160 ASSERT_TRUE(response != NULL);
6161 ASSERT_TRUE(response->headers != NULL);
6162 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536163 EXPECT_FALSE(response->was_fetched_via_spdy);
6164 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116165
6166 std::string response_data;
6167 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6168 EXPECT_EQ("hello world", response_data);
6169
6170 trans.reset(new HttpNetworkTransaction(session));
6171
6172 rv = trans->Start(&request, &callback, BoundNetLog());
6173 EXPECT_EQ(ERR_IO_PENDING, rv);
6174 EXPECT_EQ(OK, callback.WaitForResult());
6175
6176 response = trans->GetResponseInfo();
6177 ASSERT_TRUE(response != NULL);
6178 ASSERT_TRUE(response->headers != NULL);
6179 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536180 EXPECT_TRUE(response->was_fetched_via_spdy);
6181 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116182
6183 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6184 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426185 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6186 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116187 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426188 EXPECT_EQ("https://www.google.com/",
6189 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116190
[email protected]8e6441ca2010-08-19 05:56:386191 HttpStreamFactory::set_next_protos("");
6192 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116193}
[email protected]631f1322010-04-30 17:59:116194
[email protected]2ff8b312010-04-26 22:20:546195TEST_F(HttpNetworkTransactionTest,
6196 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386197 HttpStreamFactory::set_use_alternate_protocols(true);
6198 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546199 SessionDependencies session_deps;
6200
6201 HttpRequestInfo request;
6202 request.method = "GET";
6203 request.url = GURL("http://www.google.com/");
6204 request.load_flags = 0;
6205
6206 MockRead data_reads[] = {
6207 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356208 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546209 MockRead("hello world"),
6210 MockRead(true, OK),
6211 };
6212
6213 StaticSocketDataProvider first_transaction(
6214 data_reads, arraysize(data_reads), NULL, 0);
6215 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6216
6217 SSLSocketDataProvider ssl(true, OK);
6218 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356219 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536220 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546221 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536222 // Make sure we use ssl for spdy here.
6223 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546224
[email protected]2bd93022010-07-17 00:58:446225 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136226 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546227
[email protected]2bd93022010-07-17 00:58:446228 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6229 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546230 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136231 CreateMockRead(*resp),
6232 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546233 MockRead(true, 0, 0),
6234 };
6235
6236 scoped_refptr<DelayedSocketData> spdy_data(
6237 new DelayedSocketData(
6238 1, // wait for one write to finish before reading.
6239 spdy_reads, arraysize(spdy_reads),
6240 spdy_writes, arraysize(spdy_writes)));
6241 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6242
6243 TestCompletionCallback callback;
6244
6245 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6246
6247 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6248
[email protected]5a1d7ca2010-04-28 20:12:276249 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546250 EXPECT_EQ(ERR_IO_PENDING, rv);
6251 EXPECT_EQ(OK, callback.WaitForResult());
6252
6253 const HttpResponseInfo* response = trans->GetResponseInfo();
6254 ASSERT_TRUE(response != NULL);
6255 ASSERT_TRUE(response->headers != NULL);
6256 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6257
6258 std::string response_data;
6259 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6260 EXPECT_EQ("hello world", response_data);
6261
6262 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386263 HostPortPair host_port_pair("www.google.com", 443);
6264 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546265 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276266 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6267 BoundNetLog());
[email protected]df4b4ef2010-07-12 18:25:216268 scoped_refptr<TCPSocketParams> tcp_params =
6269 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:386270
6271 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6272 EXPECT_EQ(ERR_IO_PENDING,
6273 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6274 &callback, session->tcp_socket_pool(),
6275 BoundNetLog()));
6276 EXPECT_EQ(OK, callback.WaitForResult());
6277
6278 SSLConfig ssl_config;
6279 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6280 ClientSocket* socket = connection->release_socket();
[email protected]563ee902010-09-27 16:16:176281 socket = session->socket_factory()->CreateSSLClientSocket(socket, "" ,
6282 ssl_config);
[email protected]02b0c342010-09-25 21:09:386283 connection->set_socket(socket);
6284 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6285 EXPECT_EQ(OK, callback.WaitForResult());
6286
6287 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6288 true, OK));
6289
[email protected]2ff8b312010-04-26 22:20:546290 trans.reset(new HttpNetworkTransaction(session));
6291
[email protected]5a1d7ca2010-04-28 20:12:276292 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546293 EXPECT_EQ(ERR_IO_PENDING, rv);
6294 EXPECT_EQ(OK, callback.WaitForResult());
6295
6296 response = trans->GetResponseInfo();
6297 ASSERT_TRUE(response != NULL);
6298 ASSERT_TRUE(response->headers != NULL);
6299 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536300 EXPECT_TRUE(response->was_fetched_via_spdy);
6301 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576302 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546303
6304 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6305 EXPECT_EQ("hello!", response_data);
6306
[email protected]8e6441ca2010-08-19 05:56:386307 HttpStreamFactory::set_next_protos("");
6308 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426309}
6310
[email protected]044de0642010-06-17 10:42:156311// GenerateAuthToken is a mighty big test.
6312// It tests all permutation of GenerateAuthToken behavior:
6313// - Synchronous and Asynchronous completion.
6314// - OK or error on completion.
6315// - Direct connection, non-authenticating proxy, and authenticating proxy.
6316// - HTTP or HTTPS backend (to include proxy tunneling).
6317// - Non-authenticating and authenticating backend.
6318//
6319// In all, there are 44 reasonable permuations (for example, if there are
6320// problems generating an auth token for an authenticating proxy, we don't
6321// need to test all permutations of the backend server).
6322//
6323// The test proceeds by going over each of the configuration cases, and
6324// potentially running up to three rounds in each of the tests. The TestConfig
6325// specifies both the configuration for the test as well as the expectations
6326// for the results.
6327TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506328 static const char kServer[] = "http://www.example.com";
6329 static const char kSecureServer[] = "https://www.example.com";
6330 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156331 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6332
6333 enum AuthTiming {
6334 AUTH_NONE,
6335 AUTH_SYNC,
6336 AUTH_ASYNC,
6337 };
6338
6339 const MockWrite kGet(
6340 "GET / HTTP/1.1\r\n"
6341 "Host: www.example.com\r\n"
6342 "Connection: keep-alive\r\n\r\n");
6343 const MockWrite kGetProxy(
6344 "GET http://www.example.com/ HTTP/1.1\r\n"
6345 "Host: www.example.com\r\n"
6346 "Proxy-Connection: keep-alive\r\n\r\n");
6347 const MockWrite kGetAuth(
6348 "GET / HTTP/1.1\r\n"
6349 "Host: www.example.com\r\n"
6350 "Connection: keep-alive\r\n"
6351 "Authorization: auth_token\r\n\r\n");
6352 const MockWrite kGetProxyAuth(
6353 "GET http://www.example.com/ HTTP/1.1\r\n"
6354 "Host: www.example.com\r\n"
6355 "Proxy-Connection: keep-alive\r\n"
6356 "Proxy-Authorization: auth_token\r\n\r\n");
6357 const MockWrite kGetAuthThroughProxy(
6358 "GET http://www.example.com/ HTTP/1.1\r\n"
6359 "Host: www.example.com\r\n"
6360 "Proxy-Connection: keep-alive\r\n"
6361 "Authorization: auth_token\r\n\r\n");
6362 const MockWrite kGetAuthWithProxyAuth(
6363 "GET http://www.example.com/ HTTP/1.1\r\n"
6364 "Host: www.example.com\r\n"
6365 "Proxy-Connection: keep-alive\r\n"
6366 "Proxy-Authorization: auth_token\r\n"
6367 "Authorization: auth_token\r\n\r\n");
6368 const MockWrite kConnect(
6369 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6370 "Host: www.example.com\r\n"
6371 "Proxy-Connection: keep-alive\r\n\r\n");
6372 const MockWrite kConnectProxyAuth(
6373 "CONNECT www.example.com:443 HTTP/1.1\r\n"
6374 "Host: www.example.com\r\n"
6375 "Proxy-Connection: keep-alive\r\n"
6376 "Proxy-Authorization: auth_token\r\n\r\n");
6377
6378 const MockRead kSuccess(
6379 "HTTP/1.1 200 OK\r\n"
6380 "Content-Type: text/html; charset=iso-8859-1\r\n"
6381 "Content-Length: 3\r\n\r\n"
6382 "Yes");
6383 const MockRead kFailure(
6384 "Should not be called.");
6385 const MockRead kServerChallenge(
6386 "HTTP/1.1 401 Unauthorized\r\n"
6387 "WWW-Authenticate: Mock realm=server\r\n"
6388 "Content-Type: text/html; charset=iso-8859-1\r\n"
6389 "Content-Length: 14\r\n\r\n"
6390 "Unauthorized\r\n");
6391 const MockRead kProxyChallenge(
6392 "HTTP/1.1 407 Unauthorized\r\n"
6393 "Proxy-Authenticate: Mock realm=proxy\r\n"
6394 "Proxy-Connection: close\r\n"
6395 "Content-Type: text/html; charset=iso-8859-1\r\n"
6396 "Content-Length: 14\r\n\r\n"
6397 "Unauthorized\r\n");
6398 const MockRead kProxyConnected(
6399 "HTTP/1.1 200 Connection Established\r\n\r\n");
6400
6401 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
6402 // no constructors, but the C++ compiler on Windows warns about
6403 // unspecified data in compound literals. So, moved to using constructors,
6404 // and TestRound's created with the default constructor should not be used.
6405 struct TestRound {
6406 TestRound()
6407 : expected_rv(ERR_UNEXPECTED),
6408 extra_write(NULL),
6409 extra_read(NULL) {
6410 }
6411 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6412 int expected_rv_arg)
6413 : write(write_arg),
6414 read(read_arg),
6415 expected_rv(expected_rv_arg),
6416 extra_write(NULL),
6417 extra_read(NULL) {
6418 }
6419 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
6420 int expected_rv_arg, const MockWrite* extra_write_arg,
6421 const MockWrite* extra_read_arg)
6422 : write(write_arg),
6423 read(read_arg),
6424 expected_rv(expected_rv_arg),
6425 extra_write(extra_write_arg),
6426 extra_read(extra_read_arg) {
6427 }
6428 MockWrite write;
6429 MockRead read;
6430 int expected_rv;
6431 const MockWrite* extra_write;
6432 const MockRead* extra_read;
6433 };
6434
6435 static const int kNoSSL = 500;
6436
6437 struct TestConfig {
6438 const char* proxy_url;
6439 AuthTiming proxy_auth_timing;
6440 int proxy_auth_rv;
6441 const char* server_url;
6442 AuthTiming server_auth_timing;
6443 int server_auth_rv;
6444 int num_auth_rounds;
6445 int first_ssl_round;
6446 TestRound rounds[3];
6447 } test_configs[] = {
6448 // Non-authenticating HTTP server with a direct connection.
6449 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6450 { TestRound(kGet, kSuccess, OK)}},
6451 // Authenticating HTTP server with a direct connection.
6452 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6453 { TestRound(kGet, kServerChallenge, OK),
6454 TestRound(kGetAuth, kSuccess, OK)}},
6455 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6456 { TestRound(kGet, kServerChallenge, OK),
6457 TestRound(kGetAuth, kFailure, kAuthErr)}},
6458 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6459 { TestRound(kGet, kServerChallenge, OK),
6460 TestRound(kGetAuth, kSuccess, OK)}},
6461 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6462 { TestRound(kGet, kServerChallenge, OK),
6463 TestRound(kGetAuth, kFailure, kAuthErr)}},
6464 // Non-authenticating HTTP server through a non-authenticating proxy.
6465 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
6466 { TestRound(kGetProxy, kSuccess, OK)}},
6467 // Authenticating HTTP server through a non-authenticating proxy.
6468 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
6469 { TestRound(kGetProxy, kServerChallenge, OK),
6470 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6471 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
6472 { TestRound(kGetProxy, kServerChallenge, OK),
6473 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6474 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
6475 { TestRound(kGetProxy, kServerChallenge, OK),
6476 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
6477 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
6478 { TestRound(kGetProxy, kServerChallenge, OK),
6479 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
6480 // Non-authenticating HTTP server through an authenticating proxy.
6481 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6482 { TestRound(kGetProxy, kProxyChallenge, OK),
6483 TestRound(kGetProxyAuth, kSuccess, OK)}},
6484 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6485 { TestRound(kGetProxy, kProxyChallenge, OK),
6486 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6487 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
6488 { TestRound(kGetProxy, kProxyChallenge, OK),
6489 TestRound(kGetProxyAuth, kSuccess, OK)}},
6490 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
6491 { TestRound(kGetProxy, kProxyChallenge, OK),
6492 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
6493 // Authenticating HTTP server through an authenticating proxy.
6494 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6495 { TestRound(kGetProxy, kProxyChallenge, OK),
6496 TestRound(kGetProxyAuth, kServerChallenge, OK),
6497 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6498 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6499 { TestRound(kGetProxy, kProxyChallenge, OK),
6500 TestRound(kGetProxyAuth, kServerChallenge, OK),
6501 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6502 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
6503 { TestRound(kGetProxy, kProxyChallenge, OK),
6504 TestRound(kGetProxyAuth, kServerChallenge, OK),
6505 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6506 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
6507 { TestRound(kGetProxy, kProxyChallenge, OK),
6508 TestRound(kGetProxyAuth, kServerChallenge, OK),
6509 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6510 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6511 { TestRound(kGetProxy, kProxyChallenge, OK),
6512 TestRound(kGetProxyAuth, kServerChallenge, OK),
6513 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6514 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6515 { TestRound(kGetProxy, kProxyChallenge, OK),
6516 TestRound(kGetProxyAuth, kServerChallenge, OK),
6517 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6518 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
6519 { TestRound(kGetProxy, kProxyChallenge, OK),
6520 TestRound(kGetProxyAuth, kServerChallenge, OK),
6521 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
6522 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
6523 { TestRound(kGetProxy, kProxyChallenge, OK),
6524 TestRound(kGetProxyAuth, kServerChallenge, OK),
6525 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
6526 // Non-authenticating HTTPS server with a direct connection.
6527 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6528 { TestRound(kGet, kSuccess, OK)}},
6529 // Authenticating HTTPS server with a direct connection.
6530 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6531 { TestRound(kGet, kServerChallenge, OK),
6532 TestRound(kGetAuth, kSuccess, OK)}},
6533 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6534 { TestRound(kGet, kServerChallenge, OK),
6535 TestRound(kGetAuth, kFailure, kAuthErr)}},
6536 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6537 { TestRound(kGet, kServerChallenge, OK),
6538 TestRound(kGetAuth, kSuccess, OK)}},
6539 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6540 { TestRound(kGet, kServerChallenge, OK),
6541 TestRound(kGetAuth, kFailure, kAuthErr)}},
6542 // Non-authenticating HTTPS server with a non-authenticating proxy.
6543 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
6544 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
6545 // Authenticating HTTPS server through a non-authenticating proxy.
6546 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
6547 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6548 TestRound(kGetAuth, kSuccess, OK)}},
6549 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
6550 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6551 TestRound(kGetAuth, kFailure, kAuthErr)}},
6552 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
6553 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6554 TestRound(kGetAuth, kSuccess, OK)}},
6555 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
6556 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
6557 TestRound(kGetAuth, kFailure, kAuthErr)}},
6558 // Non-Authenticating HTTPS server through an authenticating proxy.
6559 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6560 { TestRound(kConnect, kProxyChallenge, OK),
6561 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6562 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6563 { TestRound(kConnect, kProxyChallenge, OK),
6564 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6565 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
6566 { TestRound(kConnect, kProxyChallenge, OK),
6567 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
6568 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
6569 { TestRound(kConnect, kProxyChallenge, OK),
6570 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
6571 // Authenticating HTTPS server through an authenticating proxy.
6572 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6573 { TestRound(kConnect, kProxyChallenge, OK),
6574 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6575 &kGet, &kServerChallenge),
6576 TestRound(kGetAuth, kSuccess, OK)}},
6577 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6578 { TestRound(kConnect, kProxyChallenge, OK),
6579 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6580 &kGet, &kServerChallenge),
6581 TestRound(kGetAuth, kFailure, kAuthErr)}},
6582 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
6583 { TestRound(kConnect, kProxyChallenge, OK),
6584 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6585 &kGet, &kServerChallenge),
6586 TestRound(kGetAuth, kSuccess, OK)}},
6587 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
6588 { TestRound(kConnect, kProxyChallenge, OK),
6589 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6590 &kGet, &kServerChallenge),
6591 TestRound(kGetAuth, kFailure, kAuthErr)}},
6592 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6593 { TestRound(kConnect, kProxyChallenge, OK),
6594 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6595 &kGet, &kServerChallenge),
6596 TestRound(kGetAuth, kSuccess, OK)}},
6597 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6598 { TestRound(kConnect, kProxyChallenge, OK),
6599 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6600 &kGet, &kServerChallenge),
6601 TestRound(kGetAuth, kFailure, kAuthErr)}},
6602 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
6603 { TestRound(kConnect, kProxyChallenge, OK),
6604 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6605 &kGet, &kServerChallenge),
6606 TestRound(kGetAuth, kSuccess, OK)}},
6607 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
6608 { TestRound(kConnect, kProxyChallenge, OK),
6609 TestRound(kConnectProxyAuth, kProxyConnected, OK,
6610 &kGet, &kServerChallenge),
6611 TestRound(kGetAuth, kFailure, kAuthErr)}},
6612 };
6613
6614 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:006615 HttpAuthHandlerMock::Factory* auth_factory(
6616 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:156617 session_deps.http_auth_handler_factory.reset(auth_factory);
6618
6619 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
6620 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:266621
6622 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:156623 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006624 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156625 std::string auth_challenge = "Mock realm=proxy";
6626 GURL origin(test_config.proxy_url);
6627 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6628 auth_challenge.end());
6629 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
6630 origin, BoundNetLog());
6631 auth_handler->SetGenerateExpectation(
6632 test_config.proxy_auth_timing == AUTH_ASYNC,
6633 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:156634 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
6635 }
6636 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:006637 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:156638 std::string auth_challenge = "Mock realm=server";
6639 GURL origin(test_config.server_url);
6640 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6641 auth_challenge.end());
6642 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6643 origin, BoundNetLog());
6644 auth_handler->SetGenerateExpectation(
6645 test_config.server_auth_timing == AUTH_ASYNC,
6646 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:156647 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6648 }
6649 if (test_config.proxy_url) {
6650 session_deps.proxy_service =
6651 CreateFixedProxyService(test_config.proxy_url);
6652 } else {
[email protected]ebeefff32010-09-15 05:10:026653 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:156654 }
6655
6656 HttpRequestInfo request;
6657 request.method = "GET";
6658 request.url = GURL(test_config.server_url);
6659 request.load_flags = 0;
6660
[email protected]0b0bf032010-09-21 18:08:506661 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6662 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:156663
6664 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
6665 const TestRound& read_write_round = test_config.rounds[round];
6666
6667 // Set up expected reads and writes.
6668 MockRead reads[2];
6669 reads[0] = read_write_round.read;
6670 size_t length_reads = 1;
6671 if (read_write_round.extra_read) {
6672 reads[1] = *read_write_round.extra_read;
6673 length_reads = 2;
6674 }
6675
6676 MockWrite writes[2];
6677 writes[0] = read_write_round.write;
6678 size_t length_writes = 1;
6679 if (read_write_round.extra_write) {
6680 writes[1] = *read_write_round.extra_write;
6681 length_writes = 2;
6682 }
6683 StaticSocketDataProvider data_provider(
6684 reads, length_reads, writes, length_writes);
6685 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6686
6687 // Add an SSL sequence if necessary.
6688 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
6689 if (round >= test_config.first_ssl_round)
6690 session_deps.socket_factory.AddSSLSocketDataProvider(
6691 &ssl_socket_data_provider);
6692
6693 // Start or restart the transaction.
6694 TestCompletionCallback callback;
6695 int rv;
6696 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:506697 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:156698 } else {
[email protected]0b0bf032010-09-21 18:08:506699 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:156700 }
6701 if (rv == ERR_IO_PENDING)
6702 rv = callback.WaitForResult();
6703
6704 // Compare results with expected data.
6705 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:506706 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:156707 if (read_write_round.expected_rv == OK) {
6708 EXPECT_FALSE(response == NULL);
6709 } else {
6710 EXPECT_TRUE(response == NULL);
6711 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
6712 continue;
6713 }
6714 if (round + 1 < test_config.num_auth_rounds) {
6715 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6716 } else {
6717 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6718 }
6719 }
[email protected]e5ae96a2010-04-14 20:12:456720 }
6721}
6722
[email protected]c871bce92010-07-15 21:51:146723TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
6724 // Do multi-round authentication and make sure it works correctly.
6725 SessionDependencies session_deps;
6726 HttpAuthHandlerMock::Factory* auth_factory(
6727 new HttpAuthHandlerMock::Factory());
6728 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:026729 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:146730 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
6731 session_deps.host_resolver->set_synchronous_mode(true);
6732
6733 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
6734 auth_handler->set_connection_based(true);
6735 std::string auth_challenge = "Mock realm=server";
6736 GURL origin("http://www.example.com");
6737 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
6738 auth_challenge.end());
6739 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
6740 origin, BoundNetLog());
6741 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
6742
6743 scoped_refptr<HttpNetworkSession> session = CreateSession(&session_deps);
6744 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6745
6746 int rv = OK;
6747 const HttpResponseInfo* response = NULL;
6748 HttpRequestInfo request;
6749 request.method = "GET";
6750 request.url = origin;
6751 request.load_flags = 0;
6752 TestCompletionCallback callback;
6753
6754 const MockWrite kGet(
6755 "GET / HTTP/1.1\r\n"
6756 "Host: www.example.com\r\n"
6757 "Connection: keep-alive\r\n\r\n");
6758 const MockWrite kGetAuth(
6759 "GET / HTTP/1.1\r\n"
6760 "Host: www.example.com\r\n"
6761 "Connection: keep-alive\r\n"
6762 "Authorization: auth_token\r\n\r\n");
6763
6764 const MockRead kServerChallenge(
6765 "HTTP/1.1 401 Unauthorized\r\n"
6766 "WWW-Authenticate: Mock realm=server\r\n"
6767 "Content-Type: text/html; charset=iso-8859-1\r\n"
6768 "Content-Length: 14\r\n\r\n"
6769 "Unauthorized\r\n");
6770 const MockRead kSuccess(
6771 "HTTP/1.1 200 OK\r\n"
6772 "Content-Type: text/html; charset=iso-8859-1\r\n"
6773 "Content-Length: 3\r\n\r\n"
6774 "Yes");
6775
6776 MockWrite writes[] = {
6777 // First round
6778 kGet,
6779 // Second round
6780 kGetAuth,
6781 // Third round
6782 kGetAuth,
[email protected]eca50e122010-09-11 14:03:306783 // Fourth round
6784 kGetAuth
[email protected]c871bce92010-07-15 21:51:146785 };
6786 MockRead reads[] = {
6787 // First round
6788 kServerChallenge,
6789 // Second round
6790 kServerChallenge,
6791 // Third round
[email protected]eca50e122010-09-11 14:03:306792 kServerChallenge,
6793 // Fourth round
[email protected]c871bce92010-07-15 21:51:146794 kSuccess,
6795 };
6796 StaticSocketDataProvider data_provider(reads, arraysize(reads),
6797 writes, arraysize(writes));
6798 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
6799
6800 // First round
6801 auth_handler->SetGenerateExpectation(false, OK);
6802 rv = trans->Start(&request, &callback, BoundNetLog());
6803 if (rv == ERR_IO_PENDING)
6804 rv = callback.WaitForResult();
6805 EXPECT_EQ(OK, rv);
6806 response = trans->GetResponseInfo();
6807 ASSERT_FALSE(response == NULL);
6808 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6809
6810 // Second round
6811 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446812 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:146813 if (rv == ERR_IO_PENDING)
6814 rv = callback.WaitForResult();
6815 EXPECT_EQ(OK, rv);
6816 response = trans->GetResponseInfo();
6817 ASSERT_FALSE(response == NULL);
6818 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6819
6820 // Third round
6821 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:446822 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:146823 if (rv == ERR_IO_PENDING)
6824 rv = callback.WaitForResult();
6825 EXPECT_EQ(OK, rv);
6826 response = trans->GetResponseInfo();
6827 ASSERT_FALSE(response == NULL);
6828 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:306829
6830 // Fourth round
6831 auth_handler->SetGenerateExpectation(false, OK);
6832 rv = trans->RestartWithAuth(string16(), string16(), &callback);
6833 if (rv == ERR_IO_PENDING)
6834 rv = callback.WaitForResult();
6835 EXPECT_EQ(OK, rv);
6836 response = trans->GetResponseInfo();
6837 ASSERT_FALSE(response == NULL);
6838 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:146839}
6840
[email protected]aeaca1f2010-04-20 22:05:216841class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
6842 public:
[email protected]06650c52010-06-03 00:49:176843 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:216844 : fail_all_(fail_all) {
6845 }
6846
6847 virtual MockRead GetNextRead() {
6848 if (fail_all_)
6849 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
6850
6851 return MockRead(false /* async */,
6852 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
6853 }
6854
6855 virtual MockWriteResult OnWrite(const std::string& data) {
6856 return MockWriteResult(false /* async */, data.size());
6857 }
6858
6859 void Reset() {
6860 }
6861
6862 private:
6863 const bool fail_all_;
6864};
6865
6866// Test that we restart a connection when we see a decompression failure from
6867// the peer during the handshake. (In the real world we'll restart with SSLv3
6868// and we won't offer DEFLATE in that case.)
6869TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
6870 HttpRequestInfo request;
6871 request.method = "GET";
6872 request.url = GURL("https://tlsdecompressionfailure.example.com/");
6873 request.load_flags = 0;
6874
6875 SessionDependencies session_deps;
6876 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6877 false /* fail all reads */);
6878 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6879 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:116880 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:216881 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6882 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6883 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6884 session_deps.socket_factory.AddSSLSocketDataProvider(
6885 &ssl_socket_data_provider1);
6886 session_deps.socket_factory.AddSSLSocketDataProvider(
6887 &ssl_socket_data_provider2);
6888
[email protected]e60e47a2010-07-14 03:37:186889 // Work around http://crbug.com/37454
6890 StaticSocketDataProvider bug37454_connection;
6891 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
6892 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
6893
[email protected]aeaca1f2010-04-20 22:05:216894 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6895 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6896 TestCompletionCallback callback;
6897
[email protected]5a1d7ca2010-04-28 20:12:276898 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216899 EXPECT_EQ(ERR_IO_PENDING, rv);
6900 EXPECT_EQ(OK, callback.WaitForResult());
6901
6902 const HttpResponseInfo* response = trans->GetResponseInfo();
6903 ASSERT_TRUE(response != NULL);
6904 ASSERT_TRUE(response->headers != NULL);
6905 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6906
6907 std::string response_data;
6908 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6909 EXPECT_EQ("ok.", response_data);
6910}
6911
6912// Test that we restart a connection if we get a decompression failure from the
6913// peer while reading the first bytes from the connection. This occurs when the
6914// peer cannot handle DEFLATE but we're using False Start, so we don't notice
6915// in the handshake.
6916TEST_F(HttpNetworkTransactionTest,
6917 RestartAfterTLSDecompressionFailureWithFalseStart) {
6918 HttpRequestInfo request;
6919 request.method = "GET";
6920 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
6921 request.load_flags = 0;
6922
6923 SessionDependencies session_deps;
6924 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
6925 true /* fail all reads */);
6926 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
6927 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
6928 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
6929 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
6930 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
6931 session_deps.socket_factory.AddSSLSocketDataProvider(
6932 &ssl_socket_data_provider1);
6933 session_deps.socket_factory.AddSSLSocketDataProvider(
6934 &ssl_socket_data_provider2);
6935
6936 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6937 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6938 TestCompletionCallback callback;
6939
[email protected]5a1d7ca2010-04-28 20:12:276940 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:216941 EXPECT_EQ(ERR_IO_PENDING, rv);
6942 EXPECT_EQ(OK, callback.WaitForResult());
6943
6944 const HttpResponseInfo* response = trans->GetResponseInfo();
6945 ASSERT_TRUE(response != NULL);
6946 ASSERT_TRUE(response->headers != NULL);
6947 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6948
6949 std::string response_data;
6950 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6951 EXPECT_EQ("ok.", response_data);
6952}
6953
[email protected]65041fa2010-05-21 06:56:536954// This tests the case that a request is issued via http instead of spdy after
6955// npn is negotiated.
6956TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:386957 HttpStreamFactory::set_use_alternate_protocols(true);
6958 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:536959 SessionDependencies session_deps;
6960 HttpRequestInfo request;
6961 request.method = "GET";
6962 request.url = GURL("https://www.google.com/");
6963 request.load_flags = 0;
6964
6965 MockWrite data_writes[] = {
6966 MockWrite("GET / HTTP/1.1\r\n"
6967 "Host: www.google.com\r\n"
6968 "Connection: keep-alive\r\n\r\n"),
6969 };
6970
6971 MockRead data_reads[] = {
6972 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356973 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:536974 MockRead("hello world"),
6975 MockRead(false, OK),
6976 };
6977
6978 SSLSocketDataProvider ssl(true, OK);
6979 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6980 ssl.next_proto = "http/1.1";
6981
6982 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6983
6984 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
6985 data_writes, arraysize(data_writes));
6986 session_deps.socket_factory.AddSocketDataProvider(&data);
6987
6988 TestCompletionCallback callback;
6989
6990 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6991 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6992
6993 int rv = trans->Start(&request, &callback, BoundNetLog());
6994
6995 EXPECT_EQ(ERR_IO_PENDING, rv);
6996 EXPECT_EQ(OK, callback.WaitForResult());
6997
6998 const HttpResponseInfo* response = trans->GetResponseInfo();
6999 ASSERT_TRUE(response != NULL);
7000 ASSERT_TRUE(response->headers != NULL);
7001 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7002
7003 std::string response_data;
7004 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7005 EXPECT_EQ("hello world", response_data);
7006
7007 EXPECT_FALSE(response->was_fetched_via_spdy);
7008 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577009 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537010
[email protected]8e6441ca2010-08-19 05:56:387011 HttpStreamFactory::set_next_protos("");
7012 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537013}
[email protected]26ef6582010-06-24 02:30:477014
7015TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7016 // Simulate the SSL handshake completing with an NPN negotiation
7017 // followed by an immediate server closing of the socket.
7018 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387019 HttpStreamFactory::set_use_alternate_protocols(true);
7020 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477021 SessionDependencies session_deps;
7022
7023 HttpRequestInfo request;
7024 request.method = "GET";
7025 request.url = GURL("https://www.google.com/");
7026 request.load_flags = 0;
7027
7028 SSLSocketDataProvider ssl(true, OK);
7029 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357030 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477031 ssl.was_npn_negotiated = true;
7032 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7033
[email protected]2bd93022010-07-17 00:58:447034 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137035 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477036
7037 MockRead spdy_reads[] = {
7038 MockRead(false, 0, 0) // Not async - return 0 immediately.
7039 };
7040
7041 scoped_refptr<DelayedSocketData> spdy_data(
7042 new DelayedSocketData(
7043 0, // don't wait in this case, immediate hangup.
7044 spdy_reads, arraysize(spdy_reads),
7045 spdy_writes, arraysize(spdy_writes)));
7046 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7047
7048 TestCompletionCallback callback;
7049
7050 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7051 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7052
7053 int rv = trans->Start(&request, &callback, BoundNetLog());
7054 EXPECT_EQ(ERR_IO_PENDING, rv);
7055 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7056
[email protected]8e6441ca2010-08-19 05:56:387057 HttpStreamFactory::set_next_protos("");
7058 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477059}
[email protected]65d34382010-07-01 18:12:267060
[email protected]f45c1ee2010-08-03 00:54:307061TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7062 // This test ensures that the URL passed into the proxy is upgraded
7063 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387064 HttpStreamFactory::set_use_alternate_protocols(true);
7065 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307066 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7067
7068 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7069 HttpAuthHandlerMock::Factory* auth_factory =
7070 new HttpAuthHandlerMock::Factory();
7071 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7072 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7073 auth_factory->set_do_init_from_challenge(true);
7074 session_deps.http_auth_handler_factory.reset(auth_factory);
7075
7076 HttpRequestInfo request;
7077 request.method = "GET";
7078 request.url = GURL("http://www.google.com");
7079 request.load_flags = 0;
7080
7081 // First round goes unauthenticated through the proxy.
7082 MockWrite data_writes_1[] = {
7083 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7084 "Host: www.google.com\r\n"
7085 "Proxy-Connection: keep-alive\r\n"
7086 "\r\n"),
7087 };
7088 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597089 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307090 MockRead("HTTP/1.1 200 OK\r\n"
7091 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7092 "Proxy-Connection: close\r\n"
7093 "\r\n"),
7094 };
7095 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7096 data_writes_1, arraysize(data_writes_1));
7097
7098 // Second round tries to tunnel to www.google.com due to the
7099 // Alternate-Protocol announcement in the first round. It fails due
7100 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597101 // After the failure, a tunnel is established to www.google.com using
7102 // Proxy-Authorization headers. There is then a SPDY request round.
7103 //
7104 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7105 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7106 // does a Disconnect and Connect on the same socket, rather than trying
7107 // to obtain a new one.
7108 //
7109 // NOTE: Originally, the proxy response to the second CONNECT request
7110 // simply returned another 407 so the unit test could skip the SSL connection
7111 // establishment and SPDY framing issues. Alas, the
7112 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307113 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597114
[email protected]f45c1ee2010-08-03 00:54:307115 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7116 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7117 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7118
[email protected]394816e92010-08-03 07:38:597119 MockWrite data_writes_2[] = {
7120 // First connection attempt without Proxy-Authorization.
7121 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7122 "Host: www.google.com\r\n"
7123 "Proxy-Connection: keep-alive\r\n"
7124 "\r\n"),
7125
7126 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307127 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7128 "Host: www.google.com\r\n"
7129 "Proxy-Connection: keep-alive\r\n"
7130 "Proxy-Authorization: auth_token\r\n"
7131 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307132
[email protected]394816e92010-08-03 07:38:597133 // SPDY request
7134 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307135 };
[email protected]394816e92010-08-03 07:38:597136 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7137 "Proxy-Authenticate: Mock\r\n"
7138 "Proxy-Connection: close\r\n"
7139 "\r\n");
7140 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7141 MockRead data_reads_2[] = {
7142 // First connection attempt fails
7143 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7144 MockRead(true, kRejectConnectResponse,
7145 arraysize(kRejectConnectResponse) - 1, 1),
7146
7147 // Second connection attempt passes
7148 MockRead(true, kAcceptConnectResponse,
7149 arraysize(kAcceptConnectResponse) -1, 4),
7150
7151 // SPDY response
7152 CreateMockRead(*resp.get(), 6),
7153 CreateMockRead(*data.get(), 6),
7154 MockRead(true, 0, 0, 6),
7155 };
7156 scoped_refptr<OrderedSocketData> data_2(
7157 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7158 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307159
7160 SSLSocketDataProvider ssl(true, OK);
7161 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7162 ssl.next_proto = "spdy/2";
7163 ssl.was_npn_negotiated = true;
7164
7165 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597166 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307167 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7168 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7169
7170 // First round should work and provide the Alternate-Protocol state.
7171 TestCompletionCallback callback_1;
7172 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7173 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7174 EXPECT_EQ(ERR_IO_PENDING, rv);
7175 EXPECT_EQ(OK, callback_1.WaitForResult());
7176
7177 // Second round should attempt a tunnel connect and get an auth challenge.
7178 TestCompletionCallback callback_2;
7179 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7180 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7181 EXPECT_EQ(ERR_IO_PENDING, rv);
7182 EXPECT_EQ(OK, callback_2.WaitForResult());
7183 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7184 ASSERT_FALSE(response == NULL);
7185 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7186
7187 // Restart with auth. Tunnel should work and response received.
7188 TestCompletionCallback callback_3;
7189 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7190 EXPECT_EQ(ERR_IO_PENDING, rv);
7191 EXPECT_EQ(OK, callback_3.WaitForResult());
7192
7193 // After all that work, these two lines (or actually, just the scheme) are
7194 // what this test is all about. Make sure it happens correctly.
7195 const GURL& request_url = auth_handler->request_url();
7196 EXPECT_EQ("https", request_url.scheme());
7197 EXPECT_EQ("www.google.com", request_url.host());
7198
[email protected]8e6441ca2010-08-19 05:56:387199 HttpStreamFactory::set_next_protos("");
7200 HttpStreamFactory::set_use_alternate_protocols(false);
7201}
7202
7203// Test that if we cancel the transaction as the connection is completing, that
7204// everything tears down correctly.
7205TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7206 // Setup everything about the connection to complete synchronously, so that
7207 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7208 // for is the callback from the HttpStreamRequest.
7209 // Then cancel the transaction.
7210 // Verify that we don't crash.
7211 MockConnect mock_connect(false, OK);
7212 MockRead data_reads[] = {
7213 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7214 MockRead(false, "hello world"),
7215 MockRead(false, OK),
7216 };
7217
7218 SessionDependencies session_deps;
7219 session_deps.host_resolver->set_synchronous_mode(true);
7220 scoped_ptr<HttpTransaction> trans(
7221 new HttpNetworkTransaction(CreateSession(&session_deps)));
7222
7223 HttpRequestInfo request;
7224 request.method = "GET";
7225 request.url = GURL("http://www.google.com/");
7226 request.load_flags = 0;
7227
7228 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7229 data.set_connect_data(mock_connect);
7230 session_deps.socket_factory.AddSocketDataProvider(&data);
7231
7232 TestCompletionCallback callback;
7233
7234 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7235 int rv = trans->Start(&request, &callback, log.bound());
7236 EXPECT_EQ(ERR_IO_PENDING, rv);
7237 trans.reset(); // Cancel the transaction here.
7238
7239 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307240}
7241
[email protected]76a505b2010-08-25 06:23:007242// Test a basic GET request through a proxy.
7243TEST_F(HttpNetworkTransactionTest, ProxyGet) {
7244 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7245 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7246 session_deps.net_log = log.bound().net_log();
7247 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7248
[email protected]76a505b2010-08-25 06:23:007249 HttpRequestInfo request;
7250 request.method = "GET";
7251 request.url = GURL("http://www.google.com/");
7252
7253 MockWrite data_writes1[] = {
7254 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7255 "Host: www.google.com\r\n"
7256 "Proxy-Connection: keep-alive\r\n\r\n"),
7257 };
7258
7259 MockRead data_reads1[] = {
7260 MockRead("HTTP/1.1 200 OK\r\n"),
7261 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7262 MockRead("Content-Length: 100\r\n\r\n"),
7263 MockRead(false, OK),
7264 };
7265
7266 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7267 data_writes1, arraysize(data_writes1));
7268 session_deps.socket_factory.AddSocketDataProvider(&data1);
7269
7270 TestCompletionCallback callback1;
7271
[email protected]0b0bf032010-09-21 18:08:507272 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7273
[email protected]76a505b2010-08-25 06:23:007274 int rv = trans->Start(&request, &callback1, log.bound());
7275 EXPECT_EQ(ERR_IO_PENDING, rv);
7276
7277 rv = callback1.WaitForResult();
7278 EXPECT_EQ(OK, rv);
7279
7280 const HttpResponseInfo* response = trans->GetResponseInfo();
7281 ASSERT_FALSE(response == NULL);
7282
7283 EXPECT_TRUE(response->headers->IsKeepAlive());
7284 EXPECT_EQ(200, response->headers->response_code());
7285 EXPECT_EQ(100, response->headers->GetContentLength());
7286 EXPECT_TRUE(response->was_fetched_via_proxy);
7287 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7288}
7289
7290// Test a basic HTTPS GET request through a proxy.
7291TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
7292 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7293 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7294 session_deps.net_log = log.bound().net_log();
7295 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7296
[email protected]76a505b2010-08-25 06:23:007297 HttpRequestInfo request;
7298 request.method = "GET";
7299 request.url = GURL("https://www.google.com/");
7300
7301 // Since we have proxy, should try to establish tunnel.
7302 MockWrite data_writes1[] = {
7303 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7304 "Host: www.google.com\r\n"
7305 "Proxy-Connection: keep-alive\r\n\r\n"),
7306
7307 MockWrite("GET / HTTP/1.1\r\n"
7308 "Host: www.google.com\r\n"
7309 "Connection: keep-alive\r\n\r\n"),
7310 };
7311
7312 MockRead data_reads1[] = {
7313 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7314
7315 MockRead("HTTP/1.1 200 OK\r\n"),
7316 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7317 MockRead("Content-Length: 100\r\n\r\n"),
7318 MockRead(false, OK),
7319 };
7320
7321 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7322 data_writes1, arraysize(data_writes1));
7323 session_deps.socket_factory.AddSocketDataProvider(&data1);
7324 SSLSocketDataProvider ssl(true, OK);
7325 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7326
7327 TestCompletionCallback callback1;
7328
[email protected]0b0bf032010-09-21 18:08:507329 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7330
[email protected]76a505b2010-08-25 06:23:007331 int rv = trans->Start(&request, &callback1, log.bound());
7332 EXPECT_EQ(ERR_IO_PENDING, rv);
7333
7334 rv = callback1.WaitForResult();
7335 EXPECT_EQ(OK, rv);
7336 size_t pos = ExpectLogContainsSomewhere(
7337 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7338 NetLog::PHASE_NONE);
7339 ExpectLogContainsSomewhere(
7340 log.entries(), pos,
7341 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7342 NetLog::PHASE_NONE);
7343
7344 const HttpResponseInfo* response = trans->GetResponseInfo();
7345 ASSERT_FALSE(response == NULL);
7346
7347 EXPECT_TRUE(response->headers->IsKeepAlive());
7348 EXPECT_EQ(200, response->headers->response_code());
7349 EXPECT_EQ(100, response->headers->GetContentLength());
7350 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7351 EXPECT_TRUE(response->was_fetched_via_proxy);
7352}
7353
7354// Test a basic HTTPS GET request through a proxy, but the server hangs up
7355// while establishing the tunnel.
7356TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
7357 SessionDependencies session_deps(CreateFixedProxyService("myproxy:70"));
7358 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7359 session_deps.net_log = log.bound().net_log();
7360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7361
[email protected]76a505b2010-08-25 06:23:007362 HttpRequestInfo request;
7363 request.method = "GET";
7364 request.url = GURL("https://www.google.com/");
7365
7366 // Since we have proxy, should try to establish tunnel.
7367 MockWrite data_writes1[] = {
7368 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7369 "Host: www.google.com\r\n"
7370 "Proxy-Connection: keep-alive\r\n\r\n"),
7371
7372 MockWrite("GET / HTTP/1.1\r\n"
7373 "Host: www.google.com\r\n"
7374 "Connection: keep-alive\r\n\r\n"),
7375 };
7376
7377 MockRead data_reads1[] = {
7378 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
7379 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7380 MockRead(true, 0, 0), // EOF
7381 };
7382
7383 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7384 data_writes1, arraysize(data_writes1));
7385 session_deps.socket_factory.AddSocketDataProvider(&data1);
7386 SSLSocketDataProvider ssl(true, OK);
7387 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7388
7389 TestCompletionCallback callback1;
7390
[email protected]0b0bf032010-09-21 18:08:507391 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7392
[email protected]76a505b2010-08-25 06:23:007393 int rv = trans->Start(&request, &callback1, log.bound());
7394 EXPECT_EQ(ERR_IO_PENDING, rv);
7395
7396 rv = callback1.WaitForResult();
7397 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
7398 size_t pos = ExpectLogContainsSomewhere(
7399 log.entries(), 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
7400 NetLog::PHASE_NONE);
7401 ExpectLogContainsSomewhere(
7402 log.entries(), pos,
7403 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7404 NetLog::PHASE_NONE);
7405}
7406
[email protected]749eefa82010-09-13 22:14:037407// Test for crbug.com/55424.
7408TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
7409 SessionDependencies session_deps;
7410
7411 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
7412 "https://www.google.com", false, 1, LOWEST));
7413 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
7414
7415 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7416 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7417 MockRead spdy_reads[] = {
7418 CreateMockRead(*resp),
7419 CreateMockRead(*data),
7420 MockRead(true, 0, 0),
7421 };
7422
7423 scoped_refptr<DelayedSocketData> spdy_data(
7424 new DelayedSocketData(
7425 1, // wait for one write to finish before reading.
7426 spdy_reads, arraysize(spdy_reads),
7427 spdy_writes, arraysize(spdy_writes)));
7428 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7429
7430 SSLSocketDataProvider ssl(true, OK);
7431 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7432 ssl.next_proto = "spdy/2";
7433 ssl.was_npn_negotiated = true;
7434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7435
7436 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7437
7438 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387439 HostPortPair host_port_pair("www.google.com", 443);
7440 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:037441 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:277442 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
7443 BoundNetLog());
[email protected]749eefa82010-09-13 22:14:037444 scoped_refptr<TCPSocketParams> tcp_params =
7445 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false);
[email protected]02b0c342010-09-25 21:09:387446 TestCompletionCallback callback;
7447
7448 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7449 EXPECT_EQ(ERR_IO_PENDING,
7450 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
7451 &callback, session->tcp_socket_pool(),
7452 BoundNetLog()));
7453 EXPECT_EQ(OK, callback.WaitForResult());
7454 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:037455
7456 HttpRequestInfo request;
7457 request.method = "GET";
7458 request.url = GURL("https://www.google.com/");
7459 request.load_flags = 0;
7460
7461 // This is the important line that marks this as a preconnect.
7462 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
7463
7464 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7465
[email protected]749eefa82010-09-13 22:14:037466 int rv = trans->Start(&request, &callback, BoundNetLog());
7467 EXPECT_EQ(ERR_IO_PENDING, rv);
7468 EXPECT_EQ(OK, callback.WaitForResult());
7469}
7470
[email protected]89ceba9a2009-03-21 03:46:067471} // namespace net