blob: 260de13f9a3cbe2fdbe1ade93d82454d1b82077a [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"
[email protected]3deb9a52010-11-11 00:24:4031#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5232#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5633#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5734#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3835#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5337#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1138#include "net/proxy/proxy_resolver.h"
39#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4440#include "net/socket/client_socket_factory.h"
41#include "net/socket/socket_test_util.h"
42#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5443#include "net/spdy/spdy_framer.h"
44#include "net/spdy/spdy_session.h"
45#include "net/spdy/spdy_session_pool.h"
46#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5247#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1548#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5249
50//-----------------------------------------------------------------------------
51
[email protected]13c8a092010-07-29 06:15:4452namespace {
53
54const string16 kBar(ASCIIToUTF16("bar"));
55const string16 kBar2(ASCIIToUTF16("bar2"));
56const string16 kBar3(ASCIIToUTF16("bar3"));
57const string16 kBaz(ASCIIToUTF16("baz"));
58const string16 kFirst(ASCIIToUTF16("first"));
59const string16 kFoo(ASCIIToUTF16("foo"));
60const string16 kFoo2(ASCIIToUTF16("foo2"));
61const string16 kFoo3(ASCIIToUTF16("foo3"));
62const string16 kFou(ASCIIToUTF16("fou"));
63const string16 kSecond(ASCIIToUTF16("second"));
64const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
65const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
66
67} // namespace
68
[email protected]89ceba9a2009-03-21 03:46:0669namespace net {
70
[email protected]e44de5d2009-06-05 20:12:4571// Helper to manage the lifetimes of the dependencies for a
72// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4473struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5974 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4275 SessionDependencies()
76 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1577 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:0278 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1079 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0880 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5481 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5482 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5983
84 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4585 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4286 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1587 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:4288 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1089 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0890 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5491 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5492 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5993
[email protected]73c45322010-10-01 23:57:5494 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:1595 scoped_ptr<CertVerifier> cert_verifier;
[email protected]80d6524d2009-08-18 03:58:0996 scoped_refptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4297 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5998 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:5099 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:54100 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59101};
102
[email protected]228ff742009-06-05 01:19:59103HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]73c45322010-10-01 23:57:54104 return new HttpNetworkSession(session_deps->host_resolver.get(),
[email protected]822581d2010-12-16 17:27:15105 session_deps->cert_verifier.get(),
[email protected]2db580532010-10-08 14:32:37106 NULL /* dnsrr_resolver */,
[email protected]345c613b2010-11-22 19:33:18107 NULL /* dns_cert_checker */,
[email protected]7ab5bbd12010-10-19 13:33:21108 NULL /* ssl_host_info_factory */,
[email protected]80d6524d2009-08-18 03:58:09109 session_deps->proxy_service,
[email protected]db36938c2009-08-19 21:48:42110 &session_deps->socket_factory,
[email protected]d1eda932009-11-04 01:03:10111 session_deps->ssl_config_service,
[email protected]87bfa3f2010-09-30 14:54:56112 new SpdySessionPool(NULL),
[email protected]06650c52010-06-03 00:49:17113 session_deps->http_auth_handler_factory.get(),
[email protected]ac039522010-06-15 16:39:44114 NULL,
[email protected]a7ea8832010-07-12 17:54:54115 session_deps->net_log);
[email protected]e8d536192008-10-17 22:21:14116}
117
[email protected]89836e22008-09-25 20:33:42118class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52119 public:
[email protected]2ff8b312010-04-26 22:20:54120 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50121 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
122 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54123 spdy::SpdyFramer::set_enable_compression_default(false);
124 }
125
[email protected]0e75a732008-10-16 20:36:09126 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50127 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
128 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54129 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09130 // Empty the current queue.
131 MessageLoop::current()->RunAllPending();
132 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50133 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
134 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09135 }
136
[email protected]3d2a59b2008-09-26 19:44:25137 protected:
138 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52139
[email protected]ff007e162009-05-23 09:13:15140 struct SimpleGetHelperResult {
141 int rv;
142 std::string status_line;
143 std::string response_data;
144 };
initial.commit586acc5fe2008-07-26 22:42:52145
[email protected]31a2bfe2010-02-09 08:03:39146 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
147 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15148 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52149
[email protected]228ff742009-06-05 01:19:59150 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40151 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43152 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]ff007e162009-05-23 09:13:15154 HttpRequestInfo request;
155 request.method = "GET";
156 request.url = GURL("http://www.google.com/");
157 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52158
[email protected]31a2bfe2010-02-09 08:03:39159 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59160 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52161
[email protected]ff007e162009-05-23 09:13:15162 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52163
[email protected]169d0012010-05-10 23:20:12164 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40165 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12166 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15167 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52168
[email protected]ff007e162009-05-23 09:13:15169 out.rv = callback.WaitForResult();
170 if (out.rv != OK)
171 return out;
172
173 const HttpResponseInfo* response = trans->GetResponseInfo();
174 EXPECT_TRUE(response != NULL);
175
176 EXPECT_TRUE(response->headers != NULL);
177 out.status_line = response->headers->GetStatusLine();
178
179 rv = ReadTransaction(trans.get(), &out.response_data);
180 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40181
182 net::CapturingNetLog::EntryList entries;
183 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39184 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40185 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12186 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39187 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40188 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39189 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
190 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15191
[email protected]b2fcd0e2010-12-01 15:19:40192 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40193 NetLogHttpRequestParameter* request_params =
194 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
195 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
196 EXPECT_EQ("Host: www.google.com\r\n"
197 "Connection: keep-alive\r\n\r\n",
198 request_params->GetHeaders().ToString());
199
[email protected]aecfbf22008-10-16 02:02:47200 return out;
[email protected]ff007e162009-05-23 09:13:15201 }
initial.commit586acc5fe2008-07-26 22:42:52202
[email protected]ff007e162009-05-23 09:13:15203 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
204 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52205
[email protected]ff007e162009-05-23 09:13:15206 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15207};
[email protected]231d5a32008-09-13 00:45:27208
[email protected]15a5ccf82008-10-23 19:57:43209// Fill |str| with a long header list that consumes >= |size| bytes.
210void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19211 const char* row =
212 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
213 const int sizeof_row = strlen(row);
214 const int num_rows = static_cast<int>(
215 ceil(static_cast<float>(size) / sizeof_row));
216 const int sizeof_data = num_rows * sizeof_row;
217 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43218 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51219
[email protected]4ddaf2502008-10-23 18:26:19220 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43221 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19222}
223
[email protected]385a4672009-03-11 22:21:29224// Alternative functions that eliminate randomness and dependency on the local
225// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20226void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29227 static const uint8 bytes[] = {
228 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
229 };
230 static size_t current_byte = 0;
231 for (size_t i = 0; i < n; ++i) {
232 output[i] = bytes[current_byte++];
233 current_byte %= arraysize(bytes);
234 }
235}
236
[email protected]fe2bc6a2009-03-23 16:52:20237void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29238 static const uint8 bytes[] = {
239 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
240 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
241 };
242 static size_t current_byte = 0;
243 for (size_t i = 0; i < n; ++i) {
244 output[i] = bytes[current_byte++];
245 current_byte %= arraysize(bytes);
246 }
247}
248
[email protected]fe2bc6a2009-03-23 16:52:20249std::string MockGetHostName() {
250 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29251}
252
[email protected]e60e47a2010-07-14 03:37:18253template<typename ParentPool>
254class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31255 public:
[email protected]e60e47a2010-07-14 03:37:18256 explicit CaptureGroupNameSocketPool(HttpNetworkSession* session);
257
[email protected]d80a4322009-08-14 07:07:49258 const std::string last_group_name_received() const {
259 return last_group_name_;
260 }
261
[email protected]684970b2009-08-14 04:54:46262 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49263 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31264 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31265 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46266 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53267 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31268 last_group_name_ = group_name;
269 return ERR_IO_PENDING;
270 }
[email protected]04e5be32009-06-26 20:00:31271 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21272 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31273 virtual void ReleaseSocket(const std::string& group_name,
274 ClientSocket* socket) {}
275 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31276 virtual int IdleSocketCount() const {
277 return 0;
278 }
279 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
280 return 0;
281 }
282 virtual LoadState GetLoadState(const std::string& group_name,
283 const ClientSocketHandle* handle) const {
284 return LOAD_STATE_IDLE;
285 }
[email protected]a796bcec2010-03-22 17:17:26286 virtual base::TimeDelta ConnectionTimeout() const {
287 return base::TimeDelta();
288 }
[email protected]d80a4322009-08-14 07:07:49289
290 private:
[email protected]04e5be32009-06-26 20:00:31291 std::string last_group_name_;
292};
293
[email protected]2d731a32010-04-29 01:04:06294typedef CaptureGroupNameSocketPool<TCPClientSocketPool>
[email protected]2227c692010-05-04 15:36:11295CaptureGroupNameTCPSocketPool;
[email protected]e772db3f2010-07-12 18:11:13296typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
297CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06298typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11299CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18300typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
301CaptureGroupNameSSLSocketPool;
302
303template<typename ParentPool>
304CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
305 HttpNetworkSession* session)
306 : ParentPool(0, 0, NULL, session->host_resolver(), NULL, NULL) {}
307
308template<>
[email protected]2df19bb2010-08-25 20:13:46309CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
310 HttpNetworkSession* session)
311 : HttpProxyClientSocketPool(0, 0, NULL, session->host_resolver(), NULL,
312 NULL, NULL) {}
313
314template<>
[email protected]e60e47a2010-07-14 03:37:18315CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
316 HttpNetworkSession* session)
[email protected]822581d2010-12-16 17:27:15317 : SSLClientSocketPool(0, 0, NULL, session->host_resolver(),
318 session->cert_verifier(), NULL, NULL,
[email protected]345c613b2010-11-22 19:33:18319 NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11320
[email protected]231d5a32008-09-13 00:45:27321//-----------------------------------------------------------------------------
322
[email protected]dae22c52010-07-30 02:16:35323// This is the expected list of advertised protocols from the browser's NPN
324// list.
325static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
326
327// This is the expected return from a current server advertising SPDY.
328static const char kAlternateProtocolHttpHeader[] =
329 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
330
[email protected]231d5a32008-09-13 00:45:27331TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59332 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40333 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43334 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27335}
336
337TEST_F(HttpNetworkTransactionTest, SimpleGET) {
338 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35339 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
340 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42341 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27342 };
[email protected]31a2bfe2010-02-09 08:03:39343 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
344 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42345 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27346 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
347 EXPECT_EQ("hello world", out.response_data);
348}
349
350// Response with no status line.
351TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
352 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35353 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42354 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27355 };
[email protected]31a2bfe2010-02-09 08:03:39356 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
357 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42358 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27359 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
360 EXPECT_EQ("hello world", out.response_data);
361}
362
363// Allow up to 4 bytes of junk to precede status line.
364TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
365 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35366 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42367 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27368 };
[email protected]31a2bfe2010-02-09 08:03:39369 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
370 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42371 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27372 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
373 EXPECT_EQ("DATA", out.response_data);
374}
375
376// Allow up to 4 bytes of junk to precede status line.
377TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
378 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35379 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42380 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27381 };
[email protected]31a2bfe2010-02-09 08:03:39382 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
383 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42384 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27385 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
386 EXPECT_EQ("DATA", out.response_data);
387}
388
389// Beyond 4 bytes of slop and it should fail to find a status line.
390TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
391 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35392 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42393 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27394 };
[email protected]31a2bfe2010-02-09 08:03:39395 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
396 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42397 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25398 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
399 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27400}
401
402// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
403TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
404 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35405 MockRead("\n"),
406 MockRead("\n"),
407 MockRead("Q"),
408 MockRead("J"),
409 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42410 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27411 };
[email protected]31a2bfe2010-02-09 08:03:39412 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
413 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42414 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27415 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
416 EXPECT_EQ("DATA", out.response_data);
417}
418
419// Close the connection before enough bytes to have a status line.
420TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
421 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35422 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42423 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27424 };
[email protected]31a2bfe2010-02-09 08:03:39425 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
426 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42427 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27428 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
429 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52430}
431
[email protected]f9d44aa2008-09-23 23:57:17432// Simulate a 204 response, lacking a Content-Length header, sent over a
433// persistent connection. The response should still terminate since a 204
434// cannot have a response body.
435TEST_F(HttpNetworkTransactionTest, StopsReading204) {
436 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35437 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
438 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42439 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17440 };
[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]f9d44aa2008-09-23 23:57:17444 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
445 EXPECT_EQ("", out.response_data);
446}
447
[email protected]0877e3d2009-10-17 22:29:57448// A simple request using chunked encoding with some extra data after.
449// (Like might be seen in a pipelined response.)
450TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
451 MockRead data_reads[] = {
452 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
453 MockRead("5\r\nHello\r\n"),
454 MockRead("1\r\n"),
455 MockRead(" \r\n"),
456 MockRead("5\r\nworld\r\n"),
457 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
458 MockRead(false, OK),
459 };
[email protected]31a2bfe2010-02-09 08:03:39460 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
461 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57462 EXPECT_EQ(OK, out.rv);
463 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
464 EXPECT_EQ("Hello world", out.response_data);
465}
466
[email protected]9fe44f52010-09-23 18:36:00467// Next tests deal with http://crbug.com/56344.
468
469TEST_F(HttpNetworkTransactionTest,
470 MultipleContentLengthHeadersNoTransferEncoding) {
471 MockRead data_reads[] = {
472 MockRead("HTTP/1.1 200 OK\r\n"),
473 MockRead("Content-Length: 10\r\n"),
474 MockRead("Content-Length: 5\r\n\r\n"),
475 };
476 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
477 arraysize(data_reads));
478 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
479}
480
481TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04482 DuplicateContentLengthHeadersNoTransferEncoding) {
483 MockRead data_reads[] = {
484 MockRead("HTTP/1.1 200 OK\r\n"),
485 MockRead("Content-Length: 5\r\n"),
486 MockRead("Content-Length: 5\r\n\r\n"),
487 MockRead("Hello"),
488 };
489 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
490 arraysize(data_reads));
491 EXPECT_EQ(OK, out.rv);
492 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
493 EXPECT_EQ("Hello", out.response_data);
494}
495
496TEST_F(HttpNetworkTransactionTest,
497 ComplexContentLengthHeadersNoTransferEncoding) {
498 // More than 2 dupes.
499 {
500 MockRead data_reads[] = {
501 MockRead("HTTP/1.1 200 OK\r\n"),
502 MockRead("Content-Length: 5\r\n"),
503 MockRead("Content-Length: 5\r\n"),
504 MockRead("Content-Length: 5\r\n\r\n"),
505 MockRead("Hello"),
506 };
507 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
508 arraysize(data_reads));
509 EXPECT_EQ(OK, out.rv);
510 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
511 EXPECT_EQ("Hello", out.response_data);
512 }
513 // HTTP/1.0
514 {
515 MockRead data_reads[] = {
516 MockRead("HTTP/1.0 200 OK\r\n"),
517 MockRead("Content-Length: 5\r\n"),
518 MockRead("Content-Length: 5\r\n"),
519 MockRead("Content-Length: 5\r\n\r\n"),
520 MockRead("Hello"),
521 };
522 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
523 arraysize(data_reads));
524 EXPECT_EQ(OK, out.rv);
525 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
526 EXPECT_EQ("Hello", out.response_data);
527 }
528 // 2 dupes and one mismatched.
529 {
530 MockRead data_reads[] = {
531 MockRead("HTTP/1.1 200 OK\r\n"),
532 MockRead("Content-Length: 10\r\n"),
533 MockRead("Content-Length: 10\r\n"),
534 MockRead("Content-Length: 5\r\n\r\n"),
535 };
536 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
537 arraysize(data_reads));
538 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
539 }
540}
541
542TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00543 MultipleContentLengthHeadersTransferEncoding) {
544 MockRead data_reads[] = {
545 MockRead("HTTP/1.1 200 OK\r\n"),
546 MockRead("Content-Length: 666\r\n"),
547 MockRead("Content-Length: 1337\r\n"),
548 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
549 MockRead("5\r\nHello\r\n"),
550 MockRead("1\r\n"),
551 MockRead(" \r\n"),
552 MockRead("5\r\nworld\r\n"),
553 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
554 MockRead(false, OK),
555 };
556 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
557 arraysize(data_reads));
558 EXPECT_EQ(OK, out.rv);
559 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
560 EXPECT_EQ("Hello world", out.response_data);
561}
562
[email protected]ef0faf2e72009-03-05 23:27:23563// Do a request using the HEAD method. Verify that we don't try to read the
564// message body (since HEAD has none).
565TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]228ff742009-06-05 01:19:59566 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40567 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43568 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ef0faf2e72009-03-05 23:27:23569
[email protected]1c773ea12009-04-28 19:58:42570 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23571 request.method = "HEAD";
572 request.url = GURL("http://www.google.com/");
573 request.load_flags = 0;
574
575 MockWrite data_writes1[] = {
576 MockWrite("HEAD / HTTP/1.1\r\n"
577 "Host: www.google.com\r\n"
578 "Connection: keep-alive\r\n"
579 "Content-Length: 0\r\n\r\n"),
580 };
581 MockRead data_reads1[] = {
582 MockRead("HTTP/1.1 404 Not Found\r\n"),
583 MockRead("Server: Blah\r\n"),
584 MockRead("Content-Length: 1234\r\n\r\n"),
585
586 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42587 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23588 };
589
[email protected]31a2bfe2010-02-09 08:03:39590 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
591 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59592 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23593
594 TestCompletionCallback callback1;
595
[email protected]5a1d7ca2010-04-28 20:12:27596 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42597 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23598
599 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42600 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23601
[email protected]1c773ea12009-04-28 19:58:42602 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23603 EXPECT_FALSE(response == NULL);
604
605 // Check that the headers got parsed.
606 EXPECT_TRUE(response->headers != NULL);
607 EXPECT_EQ(1234, response->headers->GetContentLength());
608 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
609
610 std::string server_header;
611 void* iter = NULL;
612 bool has_server_header = response->headers->EnumerateHeader(
613 &iter, "Server", &server_header);
614 EXPECT_TRUE(has_server_header);
615 EXPECT_EQ("Blah", server_header);
616
617 // Reading should give EOF right away, since there is no message body
618 // (despite non-zero content-length).
619 std::string response_data;
620 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42621 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23622 EXPECT_EQ("", response_data);
623}
624
initial.commit586acc5fe2008-07-26 22:42:52625TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59626 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52628
629 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35630 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
631 MockRead("hello"),
632 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
633 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42634 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52635 };
[email protected]31a2bfe2010-02-09 08:03:39636 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59637 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52638
[email protected]0b0bf032010-09-21 18:08:50639 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52640 "hello", "world"
641 };
642
643 for (int i = 0; i < 2; ++i) {
[email protected]5695b8c2009-09-30 21:36:43644 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52645
[email protected]1c773ea12009-04-28 19:58:42646 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52647 request.method = "GET";
648 request.url = GURL("http://www.google.com/");
649 request.load_flags = 0;
650
651 TestCompletionCallback callback;
652
[email protected]5a1d7ca2010-04-28 20:12:27653 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42654 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52655
656 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42657 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52658
[email protected]1c773ea12009-04-28 19:58:42659 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52660 EXPECT_TRUE(response != NULL);
661
662 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25663 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52664
665 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57666 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42667 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25668 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52669 }
670}
671
672TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]228ff742009-06-05 01:19:59673 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40674 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43675 new HttpNetworkTransaction(CreateSession(&session_deps)));
initial.commit586acc5fe2008-07-26 22:42:52676
[email protected]1c773ea12009-04-28 19:58:42677 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52678 request.method = "POST";
679 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42680 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52681 request.upload_data->AppendBytes("foo", 3);
682 request.load_flags = 0;
683
684 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35685 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
686 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
687 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42688 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52689 };
[email protected]31a2bfe2010-02-09 08:03:39690 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59691 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52692
693 TestCompletionCallback callback;
694
[email protected]5a1d7ca2010-04-28 20:12:27695 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42696 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52697
698 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42699 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52700
[email protected]1c773ea12009-04-28 19:58:42701 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52702 EXPECT_TRUE(response != NULL);
703
704 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25705 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52706
707 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57708 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42709 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25710 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52711}
712
[email protected]3a2d3662009-03-27 03:49:14713// This test is almost the same as Ignores100 above, but the response contains
714// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57715// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14716TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]228ff742009-06-05 01:19:59717 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40718 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43719 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3a2d3662009-03-27 03:49:14720
[email protected]1c773ea12009-04-28 19:58:42721 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14722 request.method = "GET";
723 request.url = GURL("http://www.foo.com/");
724 request.load_flags = 0;
725
726 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57727 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
728 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14729 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42730 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14731 };
[email protected]31a2bfe2010-02-09 08:03:39732 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59733 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14734
735 TestCompletionCallback callback;
736
[email protected]5a1d7ca2010-04-28 20:12:27737 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42738 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14739
740 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42741 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14742
[email protected]1c773ea12009-04-28 19:58:42743 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14744 EXPECT_TRUE(response != NULL);
745
746 EXPECT_TRUE(response->headers != NULL);
747 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
748
749 std::string response_data;
750 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42751 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14752 EXPECT_EQ("hello world", response_data);
753}
754
[email protected]ee9410e72010-01-07 01:42:38755TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
756 SessionDependencies session_deps;
757 scoped_ptr<HttpTransaction> trans(
758 new HttpNetworkTransaction(CreateSession(&session_deps)));
759
760 HttpRequestInfo request;
761 request.method = "POST";
762 request.url = GURL("http://www.foo.com/");
763 request.load_flags = 0;
764
765 MockRead data_reads[] = {
766 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
767 MockRead(true, 0),
768 };
[email protected]31a2bfe2010-02-09 08:03:39769 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38770 session_deps.socket_factory.AddSocketDataProvider(&data);
771
772 TestCompletionCallback callback;
773
[email protected]5a1d7ca2010-04-28 20:12:27774 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38775 EXPECT_EQ(ERR_IO_PENDING, rv);
776
777 rv = callback.WaitForResult();
778 EXPECT_EQ(OK, rv);
779
780 std::string response_data;
781 rv = ReadTransaction(trans.get(), &response_data);
782 EXPECT_EQ(OK, rv);
783 EXPECT_EQ("", response_data);
784}
785
786TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
787 SessionDependencies session_deps;
788 scoped_ptr<HttpTransaction> trans(
789 new HttpNetworkTransaction(CreateSession(&session_deps)));
790
791 HttpRequestInfo request;
792 request.method = "POST";
793 request.url = GURL("http://www.foo.com/");
794 request.load_flags = 0;
795
796 MockRead data_reads[] = {
797 MockRead(true, 0),
798 };
[email protected]31a2bfe2010-02-09 08:03:39799 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38800 session_deps.socket_factory.AddSocketDataProvider(&data);
801
802 TestCompletionCallback callback;
803
[email protected]5a1d7ca2010-04-28 20:12:27804 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38805 EXPECT_EQ(ERR_IO_PENDING, rv);
806
807 rv = callback.WaitForResult();
808 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
809}
810
[email protected]3d2a59b2008-09-26 19:44:25811// read_failure specifies a read failure that should cause the network
812// transaction to resend the request.
813void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
814 const MockRead& read_failure) {
[email protected]228ff742009-06-05 01:19:59815 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27816 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52817
[email protected]1c773ea12009-04-28 19:58:42818 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52819 request.method = "GET";
820 request.url = GURL("http://www.foo.com/");
821 request.load_flags = 0;
822
823 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35824 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
825 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25826 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52827 };
[email protected]31a2bfe2010-02-09 08:03:39828 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59829 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52830
831 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35832 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
833 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42834 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52835 };
[email protected]31a2bfe2010-02-09 08:03:39836 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59837 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52838
839 const char* kExpectedResponseData[] = {
840 "hello", "world"
841 };
842
843 for (int i = 0; i < 2; ++i) {
844 TestCompletionCallback callback;
845
[email protected]5695b8c2009-09-30 21:36:43846 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52847
[email protected]5a1d7ca2010-04-28 20:12:27848 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42849 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52850
851 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42852 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52853
[email protected]1c773ea12009-04-28 19:58:42854 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52855 EXPECT_TRUE(response != NULL);
856
857 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25858 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52859
860 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57861 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42862 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25863 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52864 }
865}
[email protected]3d2a59b2008-09-26 19:44:25866
867TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42868 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25869 KeepAliveConnectionResendRequestTest(read_failure);
870}
871
872TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42873 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25874 KeepAliveConnectionResendRequestTest(read_failure);
875}
876
877TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]228ff742009-06-05 01:19:59878 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40879 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43880 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3d2a59b2008-09-26 19:44:25881
[email protected]1c773ea12009-04-28 19:58:42882 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25883 request.method = "GET";
884 request.url = GURL("http://www.google.com/");
885 request.load_flags = 0;
886
887 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42888 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35889 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
890 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42891 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25892 };
[email protected]31a2bfe2010-02-09 08:03:39893 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59894 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25895
896 TestCompletionCallback callback;
897
[email protected]5a1d7ca2010-04-28 20:12:27898 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42899 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25900
901 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42902 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25903
[email protected]1c773ea12009-04-28 19:58:42904 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25905 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25906}
907
908// What do various browsers do when the server closes a non-keepalive
909// connection without sending any response header or body?
910//
911// IE7: error page
912// Safari 3.1.2 (Windows): error page
913// Firefox 3.0.1: blank page
914// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42915// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
916// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25917TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
918 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42919 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35920 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
921 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42922 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25923 };
[email protected]31a2bfe2010-02-09 08:03:39924 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
925 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42926 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25927}
[email protected]038e9a32008-10-08 22:40:16928
[email protected]0b0bf032010-09-21 18:08:50929// Test that we correctly reuse a keep-alive connection after not explicitly
930// reading the body.
931TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13932 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27933 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]fc31d6a42010-06-24 18:05:13934
935 HttpRequestInfo request;
936 request.method = "GET";
937 request.url = GURL("http://www.foo.com/");
938 request.load_flags = 0;
939
[email protected]0b0bf032010-09-21 18:08:50940 // Note that because all these reads happen in the same
941 // StaticSocketDataProvider, it shows that the same socket is being reused for
942 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13943 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50944 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
945 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13946 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50947 MockRead("HTTP/1.1 302 Found\r\n"
948 "Content-Length: 0\r\n\r\n"),
949 MockRead("HTTP/1.1 302 Found\r\n"
950 "Content-Length: 5\r\n\r\n"
951 "hello"),
952 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
953 "Content-Length: 0\r\n\r\n"),
954 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
955 "Content-Length: 5\r\n\r\n"
956 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13957 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
958 MockRead("hello"),
959 };
960 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
961 session_deps.socket_factory.AddSocketDataProvider(&data1);
962
963 MockRead data2_reads[] = {
964 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
965 };
966 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
967 session_deps.socket_factory.AddSocketDataProvider(&data2);
968
[email protected]0b0bf032010-09-21 18:08:50969 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
970 std::string response_lines[kNumUnreadBodies];
971
972 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13973 TestCompletionCallback callback;
974
975 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
976
977 int rv = trans->Start(&request, &callback, BoundNetLog());
978 EXPECT_EQ(ERR_IO_PENDING, rv);
979
980 rv = callback.WaitForResult();
981 EXPECT_EQ(OK, rv);
982
983 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50984 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13985
[email protected]0b0bf032010-09-21 18:08:50986 ASSERT_TRUE(response->headers != NULL);
987 response_lines[i] = response->headers->GetStatusLine();
988
989 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13990 }
[email protected]0b0bf032010-09-21 18:08:50991
992 const char* const kStatusLines[] = {
993 "HTTP/1.1 204 No Content",
994 "HTTP/1.1 205 Reset Content",
995 "HTTP/1.1 304 Not Modified",
996 "HTTP/1.1 302 Found",
997 "HTTP/1.1 302 Found",
998 "HTTP/1.1 301 Moved Permanently",
999 "HTTP/1.1 301 Moved Permanently",
1000 };
1001
1002 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1003 forgot_to_update_kStatusLines);
1004
1005 for (int i = 0; i < kNumUnreadBodies; ++i)
1006 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1007
1008 TestCompletionCallback callback;
1009 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1010 int rv = trans->Start(&request, &callback, BoundNetLog());
1011 EXPECT_EQ(ERR_IO_PENDING, rv);
1012 rv = callback.WaitForResult();
1013 EXPECT_EQ(OK, rv);
1014 const HttpResponseInfo* response = trans->GetResponseInfo();
1015 ASSERT_TRUE(response != NULL);
1016 ASSERT_TRUE(response->headers != NULL);
1017 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1018 std::string response_data;
1019 rv = ReadTransaction(trans.get(), &response_data);
1020 EXPECT_EQ(OK, rv);
1021 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131022}
1023
[email protected]038e9a32008-10-08 22:40:161024// Test the request-challenge-retry sequence for basic auth.
1025// (basic auth is the easiest to mock, because it has no randomness).
1026TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]228ff742009-06-05 01:19:591027 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:401028 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431029 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:161030
[email protected]1c773ea12009-04-28 19:58:421031 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161032 request.method = "GET";
1033 request.url = GURL("http://www.google.com/");
1034 request.load_flags = 0;
1035
[email protected]f9ee6b52008-11-08 06:46:231036 MockWrite data_writes1[] = {
1037 MockWrite("GET / HTTP/1.1\r\n"
1038 "Host: www.google.com\r\n"
1039 "Connection: keep-alive\r\n\r\n"),
1040 };
1041
[email protected]038e9a32008-10-08 22:40:161042 MockRead data_reads1[] = {
1043 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1044 // Give a couple authenticate options (only the middle one is actually
1045 // supported).
[email protected]22927ad2009-09-21 19:56:191046 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161047 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1048 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1050 // Large content-length -- won't matter, as connection will be reset.
1051 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421052 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161053 };
1054
1055 // After calling trans->RestartWithAuth(), this is the request we should
1056 // be issuing -- the final header line contains the credentials.
1057 MockWrite data_writes2[] = {
1058 MockWrite("GET / HTTP/1.1\r\n"
1059 "Host: www.google.com\r\n"
1060 "Connection: keep-alive\r\n"
1061 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1062 };
1063
1064 // Lastly, the server responds with the actual content.
1065 MockRead data_reads2[] = {
1066 MockRead("HTTP/1.0 200 OK\r\n"),
1067 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1068 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421069 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161070 };
1071
[email protected]31a2bfe2010-02-09 08:03:391072 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1073 data_writes1, arraysize(data_writes1));
1074 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1075 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591076 session_deps.socket_factory.AddSocketDataProvider(&data1);
1077 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161078
1079 TestCompletionCallback callback1;
1080
[email protected]5a1d7ca2010-04-28 20:12:271081 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421082 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161083
1084 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421085 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161086
[email protected]1c773ea12009-04-28 19:58:421087 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161088 EXPECT_FALSE(response == NULL);
1089
1090 // The password prompt info should have been set in response->auth_challenge.
1091 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1092
[email protected]71e4573a2009-05-21 22:03:001093 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161094 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1095 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1096
1097 TestCompletionCallback callback2;
1098
[email protected]13c8a092010-07-29 06:15:441099 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421100 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161101
1102 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421103 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161104
1105 response = trans->GetResponseInfo();
1106 EXPECT_FALSE(response == NULL);
1107 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1108 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161109}
1110
[email protected]861fcd52009-08-26 02:33:461111TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
1112 SessionDependencies session_deps;
1113 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:431114 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]861fcd52009-08-26 02:33:461115
1116 HttpRequestInfo request;
1117 request.method = "GET";
1118 request.url = GURL("http://www.google.com/");
1119 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1120
1121 MockWrite data_writes[] = {
1122 MockWrite("GET / HTTP/1.1\r\n"
1123 "Host: www.google.com\r\n"
1124 "Connection: keep-alive\r\n\r\n"),
1125 };
1126
1127 MockRead data_reads[] = {
1128 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1129 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1130 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1131 // Large content-length -- won't matter, as connection will be reset.
1132 MockRead("Content-Length: 10000\r\n\r\n"),
1133 MockRead(false, ERR_FAILED),
1134 };
1135
[email protected]31a2bfe2010-02-09 08:03:391136 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1137 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591138 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461139 TestCompletionCallback callback;
1140
[email protected]5a1d7ca2010-04-28 20:12:271141 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461142 EXPECT_EQ(ERR_IO_PENDING, rv);
1143
1144 rv = callback.WaitForResult();
1145 EXPECT_EQ(0, rv);
1146
1147 const HttpResponseInfo* response = trans->GetResponseInfo();
1148 ASSERT_FALSE(response == NULL);
1149 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1150}
1151
[email protected]2d2697f92009-02-18 21:00:321152// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1153// connection.
1154TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]228ff742009-06-05 01:19:591155 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501156 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321157
[email protected]1c773ea12009-04-28 19:58:421158 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321159 request.method = "GET";
1160 request.url = GURL("http://www.google.com/");
1161 request.load_flags = 0;
1162
1163 MockWrite data_writes1[] = {
1164 MockWrite("GET / HTTP/1.1\r\n"
1165 "Host: www.google.com\r\n"
1166 "Connection: keep-alive\r\n\r\n"),
1167
1168 // After calling trans->RestartWithAuth(), this is the request we should
1169 // be issuing -- the final header line contains the credentials.
1170 MockWrite("GET / HTTP/1.1\r\n"
1171 "Host: www.google.com\r\n"
1172 "Connection: keep-alive\r\n"
1173 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1174 };
1175
1176 MockRead data_reads1[] = {
1177 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1178 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1179 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1180 MockRead("Content-Length: 14\r\n\r\n"),
1181 MockRead("Unauthorized\r\n"),
1182
1183 // Lastly, the server responds with the actual content.
1184 MockRead("HTTP/1.1 200 OK\r\n"),
1185 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501186 MockRead("Content-Length: 5\r\n\r\n"),
1187 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321188 };
1189
[email protected]31a2bfe2010-02-09 08:03:391190 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1191 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591192 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321193
1194 TestCompletionCallback callback1;
1195
[email protected]0b0bf032010-09-21 18:08:501196 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271197 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421198 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321199
1200 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421201 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321202
[email protected]1c773ea12009-04-28 19:58:421203 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321204 EXPECT_FALSE(response == NULL);
1205
1206 // The password prompt info should have been set in response->auth_challenge.
1207 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1208
[email protected]71e4573a2009-05-21 22:03:001209 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321210 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1211 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1212
1213 TestCompletionCallback callback2;
1214
[email protected]13c8a092010-07-29 06:15:441215 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421216 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321217
1218 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421219 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321220
1221 response = trans->GetResponseInfo();
1222 EXPECT_FALSE(response == NULL);
1223 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501224 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321225}
1226
1227// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1228// connection and with no response body to drain.
1229TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]228ff742009-06-05 01:19:591230 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501231 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321232
[email protected]1c773ea12009-04-28 19:58:421233 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321234 request.method = "GET";
1235 request.url = GURL("http://www.google.com/");
1236 request.load_flags = 0;
1237
1238 MockWrite data_writes1[] = {
1239 MockWrite("GET / HTTP/1.1\r\n"
1240 "Host: www.google.com\r\n"
1241 "Connection: keep-alive\r\n\r\n"),
1242
1243 // After calling trans->RestartWithAuth(), this is the request we should
1244 // be issuing -- the final header line contains the credentials.
1245 MockWrite("GET / HTTP/1.1\r\n"
1246 "Host: www.google.com\r\n"
1247 "Connection: keep-alive\r\n"
1248 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1249 };
1250
[email protected]2d2697f92009-02-18 21:00:321251 MockRead data_reads1[] = {
1252 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1253 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311254 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321255
1256 // Lastly, the server responds with the actual content.
1257 MockRead("HTTP/1.1 200 OK\r\n"),
1258 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501259 MockRead("Content-Length: 5\r\n\r\n"),
1260 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321261 };
1262
[email protected]31a2bfe2010-02-09 08:03:391263 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1264 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591265 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321266
1267 TestCompletionCallback callback1;
1268
[email protected]0b0bf032010-09-21 18:08:501269 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271270 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421271 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321272
1273 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421274 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321275
[email protected]1c773ea12009-04-28 19:58:421276 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321277 EXPECT_FALSE(response == NULL);
1278
1279 // The password prompt info should have been set in response->auth_challenge.
1280 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1281
[email protected]71e4573a2009-05-21 22:03:001282 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321283 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1284 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1285
1286 TestCompletionCallback callback2;
1287
[email protected]13c8a092010-07-29 06:15:441288 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421289 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321290
1291 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421292 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321293
1294 response = trans->GetResponseInfo();
1295 EXPECT_FALSE(response == NULL);
1296 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501297 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321298}
1299
1300// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1301// connection and with a large response body to drain.
1302TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]228ff742009-06-05 01:19:591303 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321305
[email protected]1c773ea12009-04-28 19:58:421306 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321307 request.method = "GET";
1308 request.url = GURL("http://www.google.com/");
1309 request.load_flags = 0;
1310
1311 MockWrite data_writes1[] = {
1312 MockWrite("GET / HTTP/1.1\r\n"
1313 "Host: www.google.com\r\n"
1314 "Connection: keep-alive\r\n\r\n"),
1315
1316 // After calling trans->RestartWithAuth(), this is the request we should
1317 // be issuing -- the final header line contains the credentials.
1318 MockWrite("GET / HTTP/1.1\r\n"
1319 "Host: www.google.com\r\n"
1320 "Connection: keep-alive\r\n"
1321 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1322 };
1323
1324 // Respond with 5 kb of response body.
1325 std::string large_body_string("Unauthorized");
1326 large_body_string.append(5 * 1024, ' ');
1327 large_body_string.append("\r\n");
1328
1329 MockRead data_reads1[] = {
1330 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1331 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1332 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1333 // 5134 = 12 + 5 * 1024 + 2
1334 MockRead("Content-Length: 5134\r\n\r\n"),
1335 MockRead(true, large_body_string.data(), large_body_string.size()),
1336
1337 // Lastly, the server responds with the actual content.
1338 MockRead("HTTP/1.1 200 OK\r\n"),
1339 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501340 MockRead("Content-Length: 5\r\n\r\n"),
1341 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321342 };
1343
[email protected]31a2bfe2010-02-09 08:03:391344 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1345 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591346 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321347
1348 TestCompletionCallback callback1;
1349
[email protected]0b0bf032010-09-21 18:08:501350 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271351 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421352 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321353
1354 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421355 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321356
[email protected]1c773ea12009-04-28 19:58:421357 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321358 EXPECT_FALSE(response == NULL);
1359
1360 // The password prompt info should have been set in response->auth_challenge.
1361 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1362
[email protected]71e4573a2009-05-21 22:03:001363 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321364 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1365 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1366
1367 TestCompletionCallback callback2;
1368
[email protected]13c8a092010-07-29 06:15:441369 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421370 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321371
1372 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421373 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321374
1375 response = trans->GetResponseInfo();
1376 EXPECT_FALSE(response == NULL);
1377 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501378 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321379}
1380
1381// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311382// connection, but the server gets impatient and closes the connection.
1383TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
1384 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:501385 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]11203f012009-11-12 23:02:311386
1387 HttpRequestInfo request;
1388 request.method = "GET";
1389 request.url = GURL("http://www.google.com/");
1390 request.load_flags = 0;
1391
1392 MockWrite data_writes1[] = {
1393 MockWrite("GET / HTTP/1.1\r\n"
1394 "Host: www.google.com\r\n"
1395 "Connection: keep-alive\r\n\r\n"),
1396 // This simulates the seemingly successful write to a closed connection
1397 // if the bug is not fixed.
1398 MockWrite("GET / HTTP/1.1\r\n"
1399 "Host: www.google.com\r\n"
1400 "Connection: keep-alive\r\n"
1401 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1402 };
1403
1404 MockRead data_reads1[] = {
1405 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1406 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1407 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1408 MockRead("Content-Length: 14\r\n\r\n"),
1409 // Tell MockTCPClientSocket to simulate the server closing the connection.
1410 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1411 MockRead("Unauthorized\r\n"),
1412 MockRead(false, OK), // The server closes the connection.
1413 };
1414
1415 // After calling trans->RestartWithAuth(), this is the request we should
1416 // be issuing -- the final header line contains the credentials.
1417 MockWrite data_writes2[] = {
1418 MockWrite("GET / HTTP/1.1\r\n"
1419 "Host: www.google.com\r\n"
1420 "Connection: keep-alive\r\n"
1421 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1422 };
1423
1424 // Lastly, the server responds with the actual content.
1425 MockRead data_reads2[] = {
1426 MockRead("HTTP/1.1 200 OK\r\n"),
1427 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501428 MockRead("Content-Length: 5\r\n\r\n"),
1429 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311430 };
1431
[email protected]31a2bfe2010-02-09 08:03:391432 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1433 data_writes1, arraysize(data_writes1));
1434 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1435 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311436 session_deps.socket_factory.AddSocketDataProvider(&data1);
1437 session_deps.socket_factory.AddSocketDataProvider(&data2);
1438
1439 TestCompletionCallback callback1;
1440
[email protected]0b0bf032010-09-21 18:08:501441 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271442 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311443 EXPECT_EQ(ERR_IO_PENDING, rv);
1444
1445 rv = callback1.WaitForResult();
1446 EXPECT_EQ(OK, rv);
1447
1448 const HttpResponseInfo* response = trans->GetResponseInfo();
1449 EXPECT_FALSE(response == NULL);
1450
1451 // The password prompt info should have been set in response->auth_challenge.
1452 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1453
1454 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1455 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1456 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1457
1458 TestCompletionCallback callback2;
1459
[email protected]13c8a092010-07-29 06:15:441460 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311461 EXPECT_EQ(ERR_IO_PENDING, rv);
1462
1463 rv = callback2.WaitForResult();
1464 EXPECT_EQ(OK, rv);
1465
1466 response = trans->GetResponseInfo();
1467 ASSERT_FALSE(response == NULL);
1468 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501469 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311470}
1471
[email protected]394816e92010-08-03 07:38:591472// Test the request-challenge-retry sequence for basic auth, over a connection
1473// that requires a restart when setting up an SSL tunnel.
1474TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
1475 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001476 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]394816e92010-08-03 07:38:591477 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1478 session_deps.net_log = log.bound().net_log();
1479 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1480
[email protected]394816e92010-08-03 07:38:591481 HttpRequestInfo request;
1482 request.method = "GET";
1483 request.url = GURL("https://www.google.com/");
1484 // when the no authentication data flag is set.
1485 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1486
1487 // Since we have proxy, should try to establish tunnel.
1488 MockWrite data_writes1[] = {
1489 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1490 "Host: www.google.com\r\n"
1491 "Proxy-Connection: keep-alive\r\n\r\n"),
1492
1493 // After calling trans->RestartWithAuth(), this is the request we should
1494 // be issuing -- the final header line contains the credentials.
1495 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1496 "Host: www.google.com\r\n"
1497 "Proxy-Connection: keep-alive\r\n"
1498 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1499
1500 MockWrite("GET / HTTP/1.1\r\n"
1501 "Host: www.google.com\r\n"
1502 "Connection: keep-alive\r\n\r\n"),
1503 };
1504
1505 // The proxy responds to the connect with a 407, using a persistent
1506 // connection.
1507 MockRead data_reads1[] = {
1508 // No credentials.
1509 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1510 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1511 MockRead("Proxy-Connection: close\r\n\r\n"),
1512
1513 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1514
1515 MockRead("HTTP/1.1 200 OK\r\n"),
1516 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501517 MockRead("Content-Length: 5\r\n\r\n"),
1518 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591519 };
1520
1521 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1522 data_writes1, arraysize(data_writes1));
1523 session_deps.socket_factory.AddSocketDataProvider(&data1);
1524 SSLSocketDataProvider ssl(true, OK);
1525 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1526
1527 TestCompletionCallback callback1;
1528
[email protected]0b0bf032010-09-21 18:08:501529 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1530
[email protected]394816e92010-08-03 07:38:591531 int rv = trans->Start(&request, &callback1, log.bound());
1532 EXPECT_EQ(ERR_IO_PENDING, rv);
1533
1534 rv = callback1.WaitForResult();
1535 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401536 net::CapturingNetLog::EntryList entries;
1537 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591538 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401539 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591540 NetLog::PHASE_NONE);
1541 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401542 entries, pos,
[email protected]394816e92010-08-03 07:38:591543 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1544 NetLog::PHASE_NONE);
1545
1546 const HttpResponseInfo* response = trans->GetResponseInfo();
1547 ASSERT_FALSE(response == NULL);
1548
1549 EXPECT_EQ(407, response->headers->response_code());
1550 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1551
1552 // The password prompt info should have been set in response->auth_challenge.
1553 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1554
1555 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1556 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1557 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1558
1559 TestCompletionCallback callback2;
1560
1561 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1562 EXPECT_EQ(ERR_IO_PENDING, rv);
1563
1564 rv = callback2.WaitForResult();
1565 EXPECT_EQ(OK, rv);
1566
1567 response = trans->GetResponseInfo();
1568 ASSERT_FALSE(response == NULL);
1569
1570 EXPECT_TRUE(response->headers->IsKeepAlive());
1571 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501572 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591573 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1574
1575 // The password prompt info should not be set.
1576 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501577
1578 trans.reset();
1579 session->FlushSocketPools();
[email protected]394816e92010-08-03 07:38:591580}
1581
[email protected]11203f012009-11-12 23:02:311582// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321583// proxy connection, when setting up an SSL tunnel.
1584TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
1585 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001586 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541587 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1588 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591589 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321590
[email protected]5695b8c2009-09-30 21:36:431591 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321592
[email protected]1c773ea12009-04-28 19:58:421593 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321594 request.method = "GET";
1595 request.url = GURL("https://www.google.com/");
[email protected]861fcd52009-08-26 02:33:461596 // Ensure that proxy authentication is attempted even
1597 // when the no authentication data flag is set.
1598 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
[email protected]2d2697f92009-02-18 21:00:321599
1600 // Since we have proxy, should try to establish tunnel.
1601 MockWrite data_writes1[] = {
1602 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451603 "Host: www.google.com\r\n"
1604 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321605
1606 // After calling trans->RestartWithAuth(), this is the request we should
1607 // be issuing -- the final header line contains the credentials.
1608 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1609 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451610 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321611 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1612 };
1613
1614 // The proxy responds to the connect with a 407, using a persistent
1615 // connection.
1616 MockRead data_reads1[] = {
1617 // No credentials.
1618 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1619 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1620 MockRead("Content-Length: 10\r\n\r\n"),
1621 MockRead("0123456789"),
1622
1623 // Wrong credentials (wrong password).
1624 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1625 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1626 MockRead("Content-Length: 10\r\n\r\n"),
1627 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421628 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321629 };
1630
[email protected]31a2bfe2010-02-09 08:03:391631 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1632 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591633 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321634
1635 TestCompletionCallback callback1;
1636
[email protected]dbb83db2010-05-11 18:13:391637 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421638 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321639
1640 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421641 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401642 net::CapturingNetLog::EntryList entries;
1643 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391644 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401645 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391646 NetLog::PHASE_NONE);
1647 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401648 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391649 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1650 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321651
[email protected]1c773ea12009-04-28 19:58:421652 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321653 EXPECT_FALSE(response == NULL);
1654
1655 EXPECT_TRUE(response->headers->IsKeepAlive());
1656 EXPECT_EQ(407, response->headers->response_code());
1657 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421658 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321659
1660 // The password prompt info should have been set in response->auth_challenge.
1661 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1662
[email protected]71e4573a2009-05-21 22:03:001663 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321664 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1665 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1666
1667 TestCompletionCallback callback2;
1668
1669 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441670 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421671 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321672
1673 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421674 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321675
1676 response = trans->GetResponseInfo();
1677 EXPECT_FALSE(response == NULL);
1678
1679 EXPECT_TRUE(response->headers->IsKeepAlive());
1680 EXPECT_EQ(407, response->headers->response_code());
1681 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421682 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321683
1684 // The password prompt info should have been set in response->auth_challenge.
1685 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1686
[email protected]71e4573a2009-05-21 22:03:001687 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321688 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1689 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131690
[email protected]e60e47a2010-07-14 03:37:181691 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1692 // out of scope.
1693 session->FlushSocketPools();
[email protected]2d2697f92009-02-18 21:00:321694}
1695
[email protected]a8e9b162009-03-12 00:06:441696// Test that we don't read the response body when we fail to establish a tunnel,
1697// even if the user cancels the proxy's auth attempt.
1698TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
1699 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001700 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441701
[email protected]e44de5d2009-06-05 20:12:451702 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441703
[email protected]5695b8c2009-09-30 21:36:431704 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441705
[email protected]1c773ea12009-04-28 19:58:421706 HttpRequestInfo request;
[email protected]a8e9b162009-03-12 00:06:441707 request.method = "GET";
1708 request.url = GURL("https://www.google.com/");
1709 request.load_flags = 0;
1710
1711 // Since we have proxy, should try to establish tunnel.
1712 MockWrite data_writes[] = {
1713 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451714 "Host: www.google.com\r\n"
1715 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441716 };
1717
1718 // The proxy responds to the connect with a 407.
1719 MockRead data_reads[] = {
1720 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1721 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1722 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421723 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441724 };
1725
[email protected]31a2bfe2010-02-09 08:03:391726 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1727 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591728 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441729
1730 TestCompletionCallback callback;
1731
[email protected]5a1d7ca2010-04-28 20:12:271732 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421733 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441734
1735 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421736 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441737
[email protected]1c773ea12009-04-28 19:58:421738 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441739 EXPECT_FALSE(response == NULL);
1740
1741 EXPECT_TRUE(response->headers->IsKeepAlive());
1742 EXPECT_EQ(407, response->headers->response_code());
1743 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421744 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441745
1746 std::string response_data;
1747 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421748 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181749
1750 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
1751 session->FlushSocketPools();
[email protected]a8e9b162009-03-12 00:06:441752}
1753
[email protected]8fdbcd22010-05-05 02:54:521754// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1755// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1756TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
1757 // We are using a DIRECT connection (i.e. no proxy) for this session.
1758 SessionDependencies session_deps;
1759 scoped_ptr<HttpTransaction> trans(
1760 new HttpNetworkTransaction(CreateSession(&session_deps)));
1761
1762 HttpRequestInfo request;
1763 request.method = "GET";
1764 request.url = GURL("http://www.google.com/");
1765 request.load_flags = 0;
1766
1767 MockWrite data_writes1[] = {
1768 MockWrite("GET / HTTP/1.1\r\n"
1769 "Host: www.google.com\r\n"
1770 "Connection: keep-alive\r\n\r\n"),
1771 };
1772
1773 MockRead data_reads1[] = {
1774 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1775 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1776 // Large content-length -- won't matter, as connection will be reset.
1777 MockRead("Content-Length: 10000\r\n\r\n"),
1778 MockRead(false, ERR_FAILED),
1779 };
1780
1781 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1782 data_writes1, arraysize(data_writes1));
1783 session_deps.socket_factory.AddSocketDataProvider(&data1);
1784
1785 TestCompletionCallback callback;
1786
1787 int rv = trans->Start(&request, &callback, BoundNetLog());
1788 EXPECT_EQ(ERR_IO_PENDING, rv);
1789
1790 rv = callback.WaitForResult();
1791 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1792}
1793
[email protected]7a67a8152010-11-05 18:31:101794// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1795// through a non-authenticating proxy. The request should fail with
1796// ERR_UNEXPECTED_PROXY_AUTH.
1797// Note that it is impossible to detect if an HTTP server returns a 407 through
1798// a non-authenticating proxy - there is nothing to indicate whether the
1799// response came from the proxy or the server, so it is treated as if the proxy
1800// issued the challenge.
1801TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
1802 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1803 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1804 session_deps.net_log = log.bound().net_log();
1805 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1806
1807 HttpRequestInfo request;
1808 request.method = "GET";
1809 request.url = GURL("https://www.google.com/");
1810
1811 // Since we have proxy, should try to establish tunnel.
1812 MockWrite data_writes1[] = {
1813 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1814 "Host: www.google.com\r\n"
1815 "Proxy-Connection: keep-alive\r\n\r\n"),
1816
1817 MockWrite("GET / HTTP/1.1\r\n"
1818 "Host: www.google.com\r\n"
1819 "Connection: keep-alive\r\n\r\n"),
1820 };
1821
1822 MockRead data_reads1[] = {
1823 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1824
1825 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1826 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1827 MockRead("\r\n"),
1828 MockRead(false, OK),
1829 };
1830
1831 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1832 data_writes1, arraysize(data_writes1));
1833 session_deps.socket_factory.AddSocketDataProvider(&data1);
1834 SSLSocketDataProvider ssl(true, OK);
1835 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1836
1837 TestCompletionCallback callback1;
1838
1839 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1840
1841 int rv = trans->Start(&request, &callback1, log.bound());
1842 EXPECT_EQ(ERR_IO_PENDING, rv);
1843
1844 rv = callback1.WaitForResult();
1845 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401846 net::CapturingNetLog::EntryList entries;
1847 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101848 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401849 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101850 NetLog::PHASE_NONE);
1851 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401852 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101853 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1854 NetLog::PHASE_NONE);
1855}
[email protected]2df19bb2010-08-25 20:13:461856
1857// Test a simple get through an HTTPS Proxy.
1858TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
1859 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001860 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461861 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1862 session_deps.net_log = log.bound().net_log();
1863 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1864
[email protected]2df19bb2010-08-25 20:13:461865 HttpRequestInfo request;
1866 request.method = "GET";
1867 request.url = GURL("http://www.google.com/");
1868
1869 // Since we have proxy, should use full url
1870 MockWrite data_writes1[] = {
1871 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1872 "Host: www.google.com\r\n"
1873 "Proxy-Connection: keep-alive\r\n\r\n"),
1874 };
1875
1876 MockRead data_reads1[] = {
1877 MockRead("HTTP/1.1 200 OK\r\n"),
1878 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1879 MockRead("Content-Length: 100\r\n\r\n"),
1880 MockRead(false, OK),
1881 };
1882
1883 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1884 data_writes1, arraysize(data_writes1));
1885 session_deps.socket_factory.AddSocketDataProvider(&data1);
1886 SSLSocketDataProvider ssl(true, OK);
1887 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1888
1889 TestCompletionCallback callback1;
1890
[email protected]0b0bf032010-09-21 18:08:501891 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1892
[email protected]2df19bb2010-08-25 20:13:461893 int rv = trans->Start(&request, &callback1, log.bound());
1894 EXPECT_EQ(ERR_IO_PENDING, rv);
1895
1896 rv = callback1.WaitForResult();
1897 EXPECT_EQ(OK, rv);
1898
1899 const HttpResponseInfo* response = trans->GetResponseInfo();
1900 ASSERT_FALSE(response == NULL);
1901
1902 EXPECT_TRUE(response->headers->IsKeepAlive());
1903 EXPECT_EQ(200, response->headers->response_code());
1904 EXPECT_EQ(100, response->headers->GetContentLength());
1905 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1906
1907 // The password prompt info should not be set.
1908 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1909}
1910
[email protected]7642b5ae2010-09-01 20:55:171911// Test a SPDY get through an HTTPS Proxy.
1912TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
1913 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001914 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171915 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1916 session_deps.net_log = log.bound().net_log();
1917 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1918
[email protected]7642b5ae2010-09-01 20:55:171919 HttpRequestInfo request;
1920 request.method = "GET";
1921 request.url = GURL("http://www.google.com/");
1922 request.load_flags = 0;
1923
1924 // fetch http://www.google.com/ via SPDY
1925 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1926 false));
1927 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1928
1929 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1930 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1931 MockRead spdy_reads[] = {
1932 CreateMockRead(*resp),
1933 CreateMockRead(*data),
1934 MockRead(true, 0, 0),
1935 };
1936
1937 scoped_refptr<DelayedSocketData> spdy_data(
1938 new DelayedSocketData(
1939 1, // wait for one write to finish before reading.
1940 spdy_reads, arraysize(spdy_reads),
1941 spdy_writes, arraysize(spdy_writes)));
1942 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1943
1944 SSLSocketDataProvider ssl(true, OK);
1945 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1946 ssl.next_proto = "spdy/2";
1947 ssl.was_npn_negotiated = true;
1948 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1949
1950 TestCompletionCallback callback1;
1951
[email protected]0b0bf032010-09-21 18:08:501952 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1953
[email protected]7642b5ae2010-09-01 20:55:171954 int rv = trans->Start(&request, &callback1, log.bound());
1955 EXPECT_EQ(ERR_IO_PENDING, rv);
1956
1957 rv = callback1.WaitForResult();
1958 EXPECT_EQ(OK, rv);
1959
1960 const HttpResponseInfo* response = trans->GetResponseInfo();
1961 ASSERT_TRUE(response != NULL);
1962 ASSERT_TRUE(response->headers != NULL);
1963 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1964
1965 std::string response_data;
1966 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1967 EXPECT_EQ(net::kUploadData, response_data);
1968}
1969
[email protected]dc7bd1c52010-11-12 00:01:131970// Test a SPDY get through an HTTPS Proxy.
1971TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
1972 // Configure against https proxy server "proxy:70".
1973 SessionDependencies session_deps(
1974 ProxyService::CreateFixed("https://proxy:70"));
1975 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1976 session_deps.net_log = log.bound().net_log();
1977 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1978
1979 HttpRequestInfo request;
1980 request.method = "GET";
1981 request.url = GURL("http://www.google.com/");
1982 request.load_flags = 0;
1983
1984 // The first request will be a bare GET, the second request will be a
1985 // GET with a Proxy-Authorization header.
1986 scoped_ptr<spdy::SpdyFrame> req_get(
1987 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
1988 const char* const kExtraAuthorizationHeaders[] = {
1989 "proxy-authorization",
1990 "Basic Zm9vOmJhcg==",
1991 };
1992 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
1993 ConstructSpdyGet(
1994 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
1995 false, 3, LOWEST, false));
1996 MockWrite spdy_writes[] = {
1997 CreateMockWrite(*req_get, 1),
1998 CreateMockWrite(*req_get_authorization, 4),
1999 };
2000
2001 // The first response is a 407 proxy authentication challenge, and the second
2002 // response will be a 200 response since the second request includes a valid
2003 // Authorization header.
2004 const char* const kExtraAuthenticationHeaders[] = {
2005 "Proxy-Authenticate",
2006 "Basic realm=\"MyRealm1\""
2007 };
2008 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2009 ConstructSpdySynReplyError(
2010 "407 Proxy Authentication Required",
2011 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2012 1));
2013 scoped_ptr<spdy::SpdyFrame> body_authentication(
2014 ConstructSpdyBodyFrame(1, true));
2015 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2016 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2017 MockRead spdy_reads[] = {
2018 CreateMockRead(*resp_authentication, 2),
2019 CreateMockRead(*body_authentication, 3),
2020 CreateMockRead(*resp_data, 5),
2021 CreateMockRead(*body_data, 6),
2022 MockRead(true, 0, 7),
2023 };
2024
2025 scoped_refptr<OrderedSocketData> data(
2026 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2027 spdy_writes, arraysize(spdy_writes)));
2028 session_deps.socket_factory.AddSocketDataProvider(data);
2029
2030 SSLSocketDataProvider ssl(true, OK);
2031 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2032 ssl.next_proto = "spdy/2";
2033 ssl.was_npn_negotiated = true;
2034 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2035
2036 TestCompletionCallback callback1;
2037
2038 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2039
2040 int rv = trans->Start(&request, &callback1, log.bound());
2041 EXPECT_EQ(ERR_IO_PENDING, rv);
2042
2043 rv = callback1.WaitForResult();
2044 EXPECT_EQ(OK, rv);
2045
2046 const HttpResponseInfo* const response = trans->GetResponseInfo();
2047
2048 ASSERT_TRUE(response != NULL);
2049 ASSERT_TRUE(response->headers != NULL);
2050 EXPECT_EQ(407, response->headers->response_code());
2051 EXPECT_TRUE(response->was_fetched_via_spdy);
2052
2053 // The password prompt info should have been set in response->auth_challenge.
2054 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2055 EXPECT_TRUE(response->auth_challenge->is_proxy);
2056 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2057 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2058 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2059
2060 TestCompletionCallback callback2;
2061
2062 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2063 EXPECT_EQ(ERR_IO_PENDING, rv);
2064
2065 rv = callback2.WaitForResult();
2066 EXPECT_EQ(OK, rv);
2067
2068 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2069
2070 ASSERT_TRUE(response_restart != NULL);
2071 ASSERT_TRUE(response_restart->headers != NULL);
2072 EXPECT_EQ(200, response_restart->headers->response_code());
2073 // The password prompt info should not be set.
2074 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2075}
2076
[email protected]d9da5fe2010-10-13 22:37:162077// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2078TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
2079 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002080 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162081 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2082 session_deps.net_log = log.bound().net_log();
2083 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2084
2085 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2086
2087 HttpRequestInfo request;
2088 request.method = "GET";
2089 request.url = GURL("https://www.google.com/");
2090 request.load_flags = 0;
2091
2092 // CONNECT to www.google.com:443 via SPDY
2093 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2094 // fetch https://www.google.com/ via HTTP
2095
2096 const char get[] = "GET / HTTP/1.1\r\n"
2097 "Host: www.google.com\r\n"
2098 "Connection: keep-alive\r\n\r\n";
2099 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2100 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2101 MockWrite spdy_writes[] = {
2102 CreateMockWrite(*connect, 1),
2103 CreateMockWrite(*wrapped_get, 3)
2104 };
2105
2106 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2107 const char resp[] = "HTTP/1.1 200 OK\r\n"
2108 "Content-Length: 10\r\n\r\n";
2109
2110 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2111 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2112 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2113 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2114 MockRead spdy_reads[] = {
2115 CreateMockRead(*conn_resp, 2, true),
2116 CreateMockRead(*wrapped_get_resp, 4, true),
2117 CreateMockRead(*wrapped_body, 5, true),
2118 CreateMockRead(*wrapped_body, 6, true),
2119 MockRead(true, 0, 7),
2120 };
2121
2122 scoped_refptr<OrderedSocketData> spdy_data(
2123 new OrderedSocketData(
2124 spdy_reads, arraysize(spdy_reads),
2125 spdy_writes, arraysize(spdy_writes)));
2126 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2127
2128 SSLSocketDataProvider ssl(true, OK);
2129 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2130 ssl.next_proto = "spdy/2";
2131 ssl.was_npn_negotiated = true;
2132 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2133 SSLSocketDataProvider ssl2(true, OK);
2134 ssl2.was_npn_negotiated = false;
2135 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2136
2137 TestCompletionCallback callback1;
2138
2139 int rv = trans->Start(&request, &callback1, log.bound());
2140 EXPECT_EQ(ERR_IO_PENDING, rv);
2141
2142 rv = callback1.WaitForResult();
2143 EXPECT_EQ(OK, rv);
2144
2145 const HttpResponseInfo* response = trans->GetResponseInfo();
2146 ASSERT_TRUE(response != NULL);
2147 ASSERT_TRUE(response->headers != NULL);
2148 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2149
2150 std::string response_data;
2151 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2152 EXPECT_EQ("1234567890", response_data);
2153}
2154
2155// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2156TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
2157 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002158 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162159 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2160 session_deps.net_log = log.bound().net_log();
2161 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2162
2163 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2164
2165 HttpRequestInfo request;
2166 request.method = "GET";
2167 request.url = GURL("https://www.google.com/");
2168 request.load_flags = 0;
2169
2170 // CONNECT to www.google.com:443 via SPDY
2171 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2172 // fetch https://www.google.com/ via SPDY
2173 const char* const kMyUrl = "https://www.google.com/";
2174 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2175 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2176 MockWrite spdy_writes[] = {
2177 CreateMockWrite(*connect, 1),
2178 CreateMockWrite(*wrapped_get, 3)
2179 };
2180
2181 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2182 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2183 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2184 ConstructWrappedSpdyFrame(get_resp, 1));
2185 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2186 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2187 MockRead spdy_reads[] = {
2188 CreateMockRead(*conn_resp, 2, true),
2189 CreateMockRead(*wrapped_get_resp, 4, true),
2190 CreateMockRead(*wrapped_body, 5, true),
2191 MockRead(true, 0, 1),
2192 };
2193
2194 scoped_refptr<OrderedSocketData> spdy_data(
2195 new OrderedSocketData(
2196 spdy_reads, arraysize(spdy_reads),
2197 spdy_writes, arraysize(spdy_writes)));
2198 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2199
2200 SSLSocketDataProvider ssl(true, OK);
2201 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2202 ssl.next_proto = "spdy/2";
2203 ssl.was_npn_negotiated = true;
2204 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2205 SSLSocketDataProvider ssl2(true, OK);
2206 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2207 ssl2.next_proto = "spdy/2";
2208 ssl2.was_npn_negotiated = true;
2209 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2210
2211 TestCompletionCallback callback1;
2212
2213 int rv = trans->Start(&request, &callback1, log.bound());
2214 EXPECT_EQ(ERR_IO_PENDING, rv);
2215
2216 rv = callback1.WaitForResult();
2217 EXPECT_EQ(OK, rv);
2218
2219 const HttpResponseInfo* response = trans->GetResponseInfo();
2220 ASSERT_TRUE(response != NULL);
2221 ASSERT_TRUE(response->headers != NULL);
2222 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2223
2224 std::string response_data;
2225 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2226 EXPECT_EQ(net::kUploadData, response_data);
2227}
2228
2229// Test a SPDY CONNECT failure through an HTTPS Proxy.
2230TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
2231 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002232 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162233 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2234 session_deps.net_log = log.bound().net_log();
2235 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2236
2237 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2238
2239 HttpRequestInfo request;
2240 request.method = "GET";
2241 request.url = GURL("https://www.google.com/");
2242 request.load_flags = 0;
2243
2244 // CONNECT to www.google.com:443 via SPDY
2245 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2246 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2247
2248 MockWrite spdy_writes[] = {
2249 CreateMockWrite(*connect, 1),
2250 CreateMockWrite(*get, 3),
2251 };
2252
2253 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2254 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2255 MockRead spdy_reads[] = {
2256 CreateMockRead(*resp, 2, true),
2257 MockRead(true, 0, 4),
2258 };
2259
2260 scoped_refptr<OrderedSocketData> spdy_data(
2261 new OrderedSocketData(
2262 spdy_reads, arraysize(spdy_reads),
2263 spdy_writes, arraysize(spdy_writes)));
2264 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2265
2266 SSLSocketDataProvider ssl(true, OK);
2267 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2268 ssl.next_proto = "spdy/2";
2269 ssl.was_npn_negotiated = true;
2270 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2271 SSLSocketDataProvider ssl2(true, OK);
2272 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2273 ssl2.next_proto = "spdy/2";
2274 ssl2.was_npn_negotiated = true;
2275 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2276
2277 TestCompletionCallback callback1;
2278
2279 int rv = trans->Start(&request, &callback1, log.bound());
2280 EXPECT_EQ(ERR_IO_PENDING, rv);
2281
2282 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292283 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162284
2285 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292286 ASSERT_FALSE(response == NULL);
2287 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162288}
2289
[email protected]2df19bb2010-08-25 20:13:462290// Test the challenge-response-retry sequence through an HTTPS Proxy
2291TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
2292 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002293 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462294 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2295 session_deps.net_log = log.bound().net_log();
2296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2297
[email protected]2df19bb2010-08-25 20:13:462298 HttpRequestInfo request;
2299 request.method = "GET";
2300 request.url = GURL("http://www.google.com/");
2301 // when the no authentication data flag is set.
2302 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2303
2304 // Since we have proxy, should use full url
2305 MockWrite data_writes1[] = {
2306 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2307 "Host: www.google.com\r\n"
2308 "Proxy-Connection: keep-alive\r\n\r\n"),
2309
2310 // After calling trans->RestartWithAuth(), this is the request we should
2311 // be issuing -- the final header line contains the credentials.
2312 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2313 "Host: www.google.com\r\n"
2314 "Proxy-Connection: keep-alive\r\n"
2315 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2316 };
2317
2318 // The proxy responds to the GET with a 407, using a persistent
2319 // connection.
2320 MockRead data_reads1[] = {
2321 // No credentials.
2322 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2323 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2324 MockRead("Proxy-Connection: keep-alive\r\n"),
2325 MockRead("Content-Length: 0\r\n\r\n"),
2326
2327 MockRead("HTTP/1.1 200 OK\r\n"),
2328 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2329 MockRead("Content-Length: 100\r\n\r\n"),
2330 MockRead(false, OK),
2331 };
2332
2333 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2334 data_writes1, arraysize(data_writes1));
2335 session_deps.socket_factory.AddSocketDataProvider(&data1);
2336 SSLSocketDataProvider ssl(true, OK);
2337 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2338
2339 TestCompletionCallback callback1;
2340
[email protected]0b0bf032010-09-21 18:08:502341 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2342
[email protected]2df19bb2010-08-25 20:13:462343 int rv = trans->Start(&request, &callback1, log.bound());
2344 EXPECT_EQ(ERR_IO_PENDING, rv);
2345
2346 rv = callback1.WaitForResult();
2347 EXPECT_EQ(OK, rv);
2348
2349 const HttpResponseInfo* response = trans->GetResponseInfo();
2350 ASSERT_FALSE(response == NULL);
2351
2352 EXPECT_EQ(407, response->headers->response_code());
2353 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2354
2355 // The password prompt info should have been set in response->auth_challenge.
2356 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2357
2358 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2359 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2360 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2361
2362 TestCompletionCallback callback2;
2363
2364 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2365 EXPECT_EQ(ERR_IO_PENDING, rv);
2366
2367 rv = callback2.WaitForResult();
2368 EXPECT_EQ(OK, rv);
2369
2370 response = trans->GetResponseInfo();
2371 ASSERT_FALSE(response == NULL);
2372
2373 EXPECT_TRUE(response->headers->IsKeepAlive());
2374 EXPECT_EQ(200, response->headers->response_code());
2375 EXPECT_EQ(100, response->headers->GetContentLength());
2376 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2377
2378 // The password prompt info should not be set.
2379 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2380}
2381
[email protected]ff007e162009-05-23 09:13:152382void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082383 const MockRead& status, int expected_status) {
2384 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:002385 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]c744cf22009-02-27 07:28:082386
[email protected]228ff742009-06-05 01:19:592387 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c744cf22009-02-27 07:28:082388
[email protected]1c773ea12009-04-28 19:58:422389 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082390 request.method = "GET";
2391 request.url = GURL("https://www.google.com/");
2392 request.load_flags = 0;
2393
2394 // Since we have proxy, should try to establish tunnel.
2395 MockWrite data_writes[] = {
2396 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452397 "Host: www.google.com\r\n"
2398 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082399 };
2400
2401 MockRead data_reads[] = {
2402 status,
2403 MockRead("Content-Length: 10\r\n\r\n"),
2404 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422405 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082406 };
2407
[email protected]31a2bfe2010-02-09 08:03:392408 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2409 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592410 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082411
2412 TestCompletionCallback callback;
2413
[email protected]0b0bf032010-09-21 18:08:502414 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2415
[email protected]5a1d7ca2010-04-28 20:12:272416 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422417 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082418
2419 rv = callback.WaitForResult();
2420 EXPECT_EQ(expected_status, rv);
2421}
2422
[email protected]ff007e162009-05-23 09:13:152423void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082424 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422425 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082426}
2427
2428TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2429 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2430}
2431
2432TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2433 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2434}
2435
2436TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2437 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2438}
2439
2440TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2441 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2442}
2443
2444TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2445 ConnectStatusHelper(
2446 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2447}
2448
2449TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2450 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2451}
2452
2453TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2454 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2455}
2456
2457TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2458 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2459}
2460
2461TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2462 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2463}
2464
2465TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2466 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2467}
2468
2469TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2470 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2471}
2472
2473TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2474 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2475}
2476
2477TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2478 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2479}
2480
2481TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2482 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2483}
2484
2485TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2486 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2487}
2488
2489TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2490 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2491}
2492
2493TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2494 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2495}
2496
2497TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2498 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2499}
2500
2501TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2502 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2503}
2504
2505TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2506 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2507}
2508
2509TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2510 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2511}
2512
2513TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2514 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2515}
2516
2517TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2518 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2519}
2520
2521TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2522 ConnectStatusHelperWithExpectedStatus(
2523 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542524 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082525}
2526
2527TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2528 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2529}
2530
2531TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2532 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2533}
2534
2535TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2536 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2537}
2538
2539TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2540 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2541}
2542
2543TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2544 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2545}
2546
2547TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2548 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2549}
2550
2551TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2552 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2553}
2554
2555TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2556 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2557}
2558
2559TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2560 ConnectStatusHelper(
2561 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2562}
2563
2564TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2565 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2566}
2567
2568TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2569 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2570}
2571
2572TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2573 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2574}
2575
2576TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2577 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2578}
2579
2580TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2581 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2582}
2583
2584TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2585 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2586}
2587
2588TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2589 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2590}
2591
[email protected]038e9a32008-10-08 22:40:162592// Test the flow when both the proxy server AND origin server require
2593// authentication. Again, this uses basic auth for both since that is
2594// the simplest to mock.
2595TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]81cdfcd2010-10-16 00:49:002596 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012597
[email protected]038e9a32008-10-08 22:40:162598 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422599 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432600 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162601
[email protected]1c773ea12009-04-28 19:58:422602 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:162603 request.method = "GET";
2604 request.url = GURL("http://www.google.com/");
2605 request.load_flags = 0;
2606
[email protected]f9ee6b52008-11-08 06:46:232607 MockWrite data_writes1[] = {
2608 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2609 "Host: www.google.com\r\n"
2610 "Proxy-Connection: keep-alive\r\n\r\n"),
2611 };
2612
[email protected]038e9a32008-10-08 22:40:162613 MockRead data_reads1[] = {
2614 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2615 // Give a couple authenticate options (only the middle one is actually
2616 // supported).
[email protected]22927ad2009-09-21 19:56:192617 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162618 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2619 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2620 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2621 // Large content-length -- won't matter, as connection will be reset.
2622 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422623 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162624 };
2625
2626 // After calling trans->RestartWithAuth() the first time, this is the
2627 // request we should be issuing -- the final header line contains the
2628 // proxy's credentials.
2629 MockWrite data_writes2[] = {
2630 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2631 "Host: www.google.com\r\n"
2632 "Proxy-Connection: keep-alive\r\n"
2633 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2634 };
2635
2636 // Now the proxy server lets the request pass through to origin server.
2637 // The origin server responds with a 401.
2638 MockRead data_reads2[] = {
2639 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2640 // Note: We are using the same realm-name as the proxy server. This is
2641 // completely valid, as realms are unique across hosts.
2642 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2643 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2644 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422645 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162646 };
2647
2648 // After calling trans->RestartWithAuth() the second time, we should send
2649 // the credentials for both the proxy and origin server.
2650 MockWrite data_writes3[] = {
2651 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2652 "Host: www.google.com\r\n"
2653 "Proxy-Connection: keep-alive\r\n"
2654 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2655 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2656 };
2657
2658 // Lastly we get the desired content.
2659 MockRead data_reads3[] = {
2660 MockRead("HTTP/1.0 200 OK\r\n"),
2661 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2662 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422663 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162664 };
2665
[email protected]31a2bfe2010-02-09 08:03:392666 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2667 data_writes1, arraysize(data_writes1));
2668 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2669 data_writes2, arraysize(data_writes2));
2670 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2671 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592672 session_deps.socket_factory.AddSocketDataProvider(&data1);
2673 session_deps.socket_factory.AddSocketDataProvider(&data2);
2674 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162675
2676 TestCompletionCallback callback1;
2677
[email protected]5a1d7ca2010-04-28 20:12:272678 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422679 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162680
2681 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422682 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162683
[email protected]1c773ea12009-04-28 19:58:422684 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162685 EXPECT_FALSE(response == NULL);
2686
2687 // The password prompt info should have been set in response->auth_challenge.
2688 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2689
[email protected]71e4573a2009-05-21 22:03:002690 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162691 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2692 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2693
2694 TestCompletionCallback callback2;
2695
[email protected]13c8a092010-07-29 06:15:442696 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422697 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162698
2699 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422700 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162701
2702 response = trans->GetResponseInfo();
2703 EXPECT_FALSE(response == NULL);
2704 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2705
[email protected]71e4573a2009-05-21 22:03:002706 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162707 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2708 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2709
2710 TestCompletionCallback callback3;
2711
[email protected]13c8a092010-07-29 06:15:442712 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422713 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162714
2715 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422716 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162717
2718 response = trans->GetResponseInfo();
2719 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2720 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162721}
[email protected]4ddaf2502008-10-23 18:26:192722
[email protected]ea9dc9a2009-09-05 00:43:322723// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2724// can't hook into its internals to cause it to generate predictable NTLM
2725// authorization headers.
2726#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292727// The NTLM authentication unit tests were generated by capturing the HTTP
2728// requests and responses using Fiddler 2 and inspecting the generated random
2729// bytes in the debugger.
2730
2731// Enter the correct password and authenticate successfully.
2732TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422733 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
[email protected]2227c692010-05-04 15:36:112734 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592735 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502736 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3f918782009-02-28 01:29:242737
[email protected]1c773ea12009-04-28 19:58:422738 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242739 request.method = "GET";
2740 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2741 request.load_flags = 0;
2742
2743 MockWrite data_writes1[] = {
2744 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2745 "Host: 172.22.68.17\r\n"
2746 "Connection: keep-alive\r\n\r\n"),
2747 };
2748
2749 MockRead data_reads1[] = {
2750 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042751 // Negotiate and NTLM are often requested together. However, we only want
2752 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2753 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242754 MockRead("WWW-Authenticate: NTLM\r\n"),
2755 MockRead("Connection: close\r\n"),
2756 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362757 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242758 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422759 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242760 };
2761
2762 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222763 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242764 // request we should be issuing -- the final header line contains a Type
2765 // 1 message.
2766 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2767 "Host: 172.22.68.17\r\n"
2768 "Connection: keep-alive\r\n"
2769 "Authorization: NTLM "
2770 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2771
2772 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2773 // (the credentials for the origin server). The second request continues
2774 // on the same connection.
2775 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2776 "Host: 172.22.68.17\r\n"
2777 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292778 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2779 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2780 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2781 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2782 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242783 };
2784
2785 MockRead data_reads2[] = {
2786 // The origin server responds with a Type 2 message.
2787 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2788 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292789 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242790 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2791 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2792 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2793 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2794 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2795 "BtAAAAAAA=\r\n"),
2796 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362797 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242798 MockRead("You are not authorized to view this page\r\n"),
2799
2800 // Lastly we get the desired content.
2801 MockRead("HTTP/1.1 200 OK\r\n"),
2802 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2803 MockRead("Content-Length: 13\r\n\r\n"),
2804 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422805 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242806 };
2807
[email protected]31a2bfe2010-02-09 08:03:392808 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2809 data_writes1, arraysize(data_writes1));
2810 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2811 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592812 session_deps.socket_factory.AddSocketDataProvider(&data1);
2813 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242814
2815 TestCompletionCallback callback1;
2816
[email protected]0b0bf032010-09-21 18:08:502817 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2818
[email protected]5a1d7ca2010-04-28 20:12:272819 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422820 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242821
2822 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422823 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242824
[email protected]0757e7702009-03-27 04:00:222825 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2826 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:442827 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:422828 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:222829 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422830 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:222831 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2832
[email protected]1c773ea12009-04-28 19:58:422833 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042834 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242835
[email protected]aef04272010-06-28 18:03:042836 // The password prompt info should have been set in
2837 // response->auth_challenge.
[email protected]3f918782009-02-28 01:29:242838 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2839
[email protected]71e4573a2009-05-21 22:03:002840 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242841 EXPECT_EQ(L"", response->auth_challenge->realm);
2842 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2843
[email protected]0757e7702009-03-27 04:00:222844 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242845
[email protected]13c8a092010-07-29 06:15:442846 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback3);
[email protected]1c773ea12009-04-28 19:58:422847 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242848
[email protected]0757e7702009-03-27 04:00:222849 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422850 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242851
2852 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042853 ASSERT_FALSE(response == NULL);
2854
[email protected]3f918782009-02-28 01:29:242855 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2856 EXPECT_EQ(13, response->headers->GetContentLength());
2857}
2858
[email protected]385a4672009-03-11 22:21:292859// Enter a wrong password, and then the correct one.
2860TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422861 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
[email protected]2227c692010-05-04 15:36:112862 MockGetHostName);
[email protected]228ff742009-06-05 01:19:592863 SessionDependencies session_deps;
[email protected]0b0bf032010-09-21 18:08:502864 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]385a4672009-03-11 22:21:292865
[email protected]1c773ea12009-04-28 19:58:422866 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292867 request.method = "GET";
2868 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2869 request.load_flags = 0;
2870
2871 MockWrite data_writes1[] = {
2872 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2873 "Host: 172.22.68.17\r\n"
2874 "Connection: keep-alive\r\n\r\n"),
2875 };
2876
2877 MockRead data_reads1[] = {
2878 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042879 // Negotiate and NTLM are often requested together. However, we only want
2880 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2881 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292882 MockRead("WWW-Authenticate: NTLM\r\n"),
2883 MockRead("Connection: close\r\n"),
2884 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362885 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292886 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422887 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292888 };
2889
2890 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222891 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292892 // request we should be issuing -- the final header line contains a Type
2893 // 1 message.
2894 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2895 "Host: 172.22.68.17\r\n"
2896 "Connection: keep-alive\r\n"
2897 "Authorization: NTLM "
2898 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2899
2900 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2901 // (the credentials for the origin server). The second request continues
2902 // on the same connection.
2903 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2904 "Host: 172.22.68.17\r\n"
2905 "Connection: keep-alive\r\n"
2906 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2907 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2908 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2909 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2910 "4Ww7b7E=\r\n\r\n"),
2911 };
2912
2913 MockRead data_reads2[] = {
2914 // The origin server responds with a Type 2 message.
2915 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2916 MockRead("WWW-Authenticate: NTLM "
2917 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2918 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2919 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2920 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2921 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2922 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2923 "BtAAAAAAA=\r\n"),
2924 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362925 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292926 MockRead("You are not authorized to view this page\r\n"),
2927
2928 // Wrong password.
2929 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292930 MockRead("WWW-Authenticate: NTLM\r\n"),
2931 MockRead("Connection: close\r\n"),
2932 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362933 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292934 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422935 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292936 };
2937
2938 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222939 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292940 // request we should be issuing -- the final header line contains a Type
2941 // 1 message.
2942 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2943 "Host: 172.22.68.17\r\n"
2944 "Connection: keep-alive\r\n"
2945 "Authorization: NTLM "
2946 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2947
2948 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2949 // (the credentials for the origin server). The second request continues
2950 // on the same connection.
2951 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2952 "Host: 172.22.68.17\r\n"
2953 "Connection: keep-alive\r\n"
2954 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2955 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2956 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2957 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2958 "+4MUm7c=\r\n\r\n"),
2959 };
2960
2961 MockRead data_reads3[] = {
2962 // The origin server responds with a Type 2 message.
2963 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2964 MockRead("WWW-Authenticate: NTLM "
2965 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
2966 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2967 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2968 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2969 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2970 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2971 "BtAAAAAAA=\r\n"),
2972 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362973 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292974 MockRead("You are not authorized to view this page\r\n"),
2975
2976 // Lastly we get the desired content.
2977 MockRead("HTTP/1.1 200 OK\r\n"),
2978 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2979 MockRead("Content-Length: 13\r\n\r\n"),
2980 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422981 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:292982 };
2983
[email protected]31a2bfe2010-02-09 08:03:392984 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2985 data_writes1, arraysize(data_writes1));
2986 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2987 data_writes2, arraysize(data_writes2));
2988 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2989 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592990 session_deps.socket_factory.AddSocketDataProvider(&data1);
2991 session_deps.socket_factory.AddSocketDataProvider(&data2);
2992 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:292993
2994 TestCompletionCallback callback1;
2995
[email protected]0b0bf032010-09-21 18:08:502996 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2997
[email protected]5a1d7ca2010-04-28 20:12:272998 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422999 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293000
3001 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423002 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293003
[email protected]0757e7702009-03-27 04:00:223004 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293005 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443006 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423007 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293008 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423009 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223010 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293011
[email protected]1c773ea12009-04-28 19:58:423012 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293013 EXPECT_FALSE(response == NULL);
3014
3015 // The password prompt info should have been set in response->auth_challenge.
3016 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3017
[email protected]71e4573a2009-05-21 22:03:003018 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293019 EXPECT_EQ(L"", response->auth_challenge->realm);
3020 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3021
3022 TestCompletionCallback callback3;
3023
[email protected]0757e7702009-03-27 04:00:223024 // Enter the wrong password.
[email protected]13c8a092010-07-29 06:15:443025 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback3);
[email protected]1c773ea12009-04-28 19:58:423026 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293027
3028 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423029 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293030
[email protected]0757e7702009-03-27 04:00:223031 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3032 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:443033 rv = trans->RestartWithAuth(string16(), string16(), &callback4);
[email protected]1c773ea12009-04-28 19:58:423034 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223035 rv = callback4.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423036 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223037 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3038
3039 response = trans->GetResponseInfo();
3040 EXPECT_FALSE(response == NULL);
3041
3042 // The password prompt info should have been set in response->auth_challenge.
3043 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3044
[email protected]71e4573a2009-05-21 22:03:003045 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223046 EXPECT_EQ(L"", response->auth_challenge->realm);
3047 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3048
3049 TestCompletionCallback callback5;
3050
3051 // Now enter the right password.
[email protected]13c8a092010-07-29 06:15:443052 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback5);
[email protected]1c773ea12009-04-28 19:58:423053 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223054
3055 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423056 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223057
[email protected]385a4672009-03-11 22:21:293058 response = trans->GetResponseInfo();
3059 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3060 EXPECT_EQ(13, response->headers->GetContentLength());
3061}
[email protected]ea9dc9a2009-09-05 00:43:323062#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293063
[email protected]4ddaf2502008-10-23 18:26:193064// Test reading a server response which has only headers, and no body.
3065// After some maximum number of bytes is consumed, the transaction should
3066// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3067TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]228ff742009-06-05 01:19:593068 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403069 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433070 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]4ddaf2502008-10-23 18:26:193071
[email protected]1c773ea12009-04-28 19:58:423072 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193073 request.method = "GET";
3074 request.url = GURL("http://www.google.com/");
3075 request.load_flags = 0;
3076
[email protected]b75b7b2f2009-10-06 00:54:533077 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433078 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533079 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193080
3081 MockRead data_reads[] = {
3082 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433083 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193084 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423085 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193086 };
[email protected]31a2bfe2010-02-09 08:03:393087 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593088 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193089
3090 TestCompletionCallback callback;
3091
[email protected]5a1d7ca2010-04-28 20:12:273092 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423093 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193094
3095 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423096 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193097
[email protected]1c773ea12009-04-28 19:58:423098 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193099 EXPECT_TRUE(response == NULL);
3100}
[email protected]f4e426b2008-11-05 00:24:493101
3102// Make sure that we don't try to reuse a TCPClientSocket when failing to
3103// establish tunnel.
3104// http://code.google.com/p/chromium/issues/detail?id=3772
3105TEST_F(HttpNetworkTransactionTest, DontRecycleTCPSocketForSSLTunnel) {
3106 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003107 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013108
[email protected]228ff742009-06-05 01:19:593109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493110
[email protected]5695b8c2009-09-30 21:36:433111 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493112
[email protected]1c773ea12009-04-28 19:58:423113 HttpRequestInfo request;
[email protected]f4e426b2008-11-05 00:24:493114 request.method = "GET";
3115 request.url = GURL("https://www.google.com/");
3116 request.load_flags = 0;
3117
3118 // Since we have proxy, should try to establish tunnel.
3119 MockWrite data_writes1[] = {
3120 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453121 "Host: www.google.com\r\n"
3122 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493123 };
3124
[email protected]77848d12008-11-14 00:00:223125 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493126 // connection. Usually a proxy would return 501 (not implemented),
3127 // or 200 (tunnel established).
3128 MockRead data_reads1[] = {
3129 MockRead("HTTP/1.1 404 Not Found\r\n"),
3130 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423131 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493132 };
3133
[email protected]31a2bfe2010-02-09 08:03:393134 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3135 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593136 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493137
3138 TestCompletionCallback callback1;
3139
[email protected]5a1d7ca2010-04-28 20:12:273140 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423141 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493142
3143 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423144 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493145
[email protected]1c773ea12009-04-28 19:58:423146 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083147 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493148
[email protected]b4404c02009-04-10 16:38:523149 // Empty the current queue. This is necessary because idle sockets are
3150 // added to the connection pool asynchronously with a PostTask.
3151 MessageLoop::current()->RunAllPending();
3152
[email protected]f4e426b2008-11-05 00:24:493153 // We now check to make sure the TCPClientSocket was not added back to
3154 // the pool.
[email protected]a937a06d2009-08-19 21:19:243155 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493156 trans.reset();
[email protected]b4404c02009-04-10 16:38:523157 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493158 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a937a06d2009-08-19 21:19:243159 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493160}
[email protected]372d34a2008-11-05 21:30:513161
[email protected]1b157c02009-04-21 01:55:403162// Make sure that we recycle a socket after reading all of the response body.
3163TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]228ff742009-06-05 01:19:593164 SessionDependencies session_deps;
3165 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]1b157c02009-04-21 01:55:403166
[email protected]5695b8c2009-09-30 21:36:433167 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]1b157c02009-04-21 01:55:403168
[email protected]1c773ea12009-04-28 19:58:423169 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403170 request.method = "GET";
3171 request.url = GURL("http://www.google.com/");
3172 request.load_flags = 0;
3173
3174 MockRead data_reads[] = {
3175 // A part of the response body is received with the response headers.
3176 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3177 // The rest of the response body is received in two parts.
3178 MockRead("lo"),
3179 MockRead(" world"),
3180 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423181 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403182 };
3183
[email protected]31a2bfe2010-02-09 08:03:393184 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593185 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403186
3187 TestCompletionCallback callback;
3188
[email protected]5a1d7ca2010-04-28 20:12:273189 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423190 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403191
3192 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423193 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403194
[email protected]1c773ea12009-04-28 19:58:423195 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403196 EXPECT_TRUE(response != NULL);
3197
3198 EXPECT_TRUE(response->headers != NULL);
3199 std::string status_line = response->headers->GetStatusLine();
3200 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3201
[email protected]a937a06d2009-08-19 21:19:243202 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403203
3204 std::string response_data;
3205 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423206 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403207 EXPECT_EQ("hello world", response_data);
3208
3209 // Empty the current queue. This is necessary because idle sockets are
3210 // added to the connection pool asynchronously with a PostTask.
3211 MessageLoop::current()->RunAllPending();
3212
3213 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243214 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403215}
3216
[email protected]76a505b2010-08-25 06:23:003217// Make sure that we recycle a SSL socket after reading all of the response
3218// body.
3219TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3220 SessionDependencies session_deps;
3221 HttpRequestInfo request;
3222 request.method = "GET";
3223 request.url = GURL("https://www.google.com/");
3224 request.load_flags = 0;
3225
3226 MockWrite data_writes[] = {
3227 MockWrite("GET / HTTP/1.1\r\n"
3228 "Host: www.google.com\r\n"
3229 "Connection: keep-alive\r\n\r\n"),
3230 };
3231
3232 MockRead data_reads[] = {
3233 MockRead("HTTP/1.1 200 OK\r\n"),
3234 MockRead("Content-Length: 11\r\n\r\n"),
3235 MockRead("hello world"),
3236 MockRead(false, OK),
3237 };
3238
3239 SSLSocketDataProvider ssl(true, OK);
3240 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3241
3242 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3243 data_writes, arraysize(data_writes));
3244 session_deps.socket_factory.AddSocketDataProvider(&data);
3245
3246 TestCompletionCallback callback;
3247
3248 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3249 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3250
3251 int rv = trans->Start(&request, &callback, BoundNetLog());
3252
3253 EXPECT_EQ(ERR_IO_PENDING, rv);
3254 EXPECT_EQ(OK, callback.WaitForResult());
3255
3256 const HttpResponseInfo* response = trans->GetResponseInfo();
3257 ASSERT_TRUE(response != NULL);
3258 ASSERT_TRUE(response->headers != NULL);
3259 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3260
3261 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3262
3263 std::string response_data;
3264 rv = ReadTransaction(trans.get(), &response_data);
3265 EXPECT_EQ(OK, rv);
3266 EXPECT_EQ("hello world", response_data);
3267
3268 // Empty the current queue. This is necessary because idle sockets are
3269 // added to the connection pool asynchronously with a PostTask.
3270 MessageLoop::current()->RunAllPending();
3271
3272 // We now check to make sure the socket was added back to the pool.
3273 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3274}
3275
3276// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3277// from the pool and make sure that we recover okay.
3278TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3279 SessionDependencies session_deps;
3280 HttpRequestInfo request;
3281 request.method = "GET";
3282 request.url = GURL("https://www.google.com/");
3283 request.load_flags = 0;
3284
3285 MockWrite data_writes[] = {
3286 MockWrite("GET / HTTP/1.1\r\n"
3287 "Host: www.google.com\r\n"
3288 "Connection: keep-alive\r\n\r\n"),
3289 MockWrite("GET / HTTP/1.1\r\n"
3290 "Host: www.google.com\r\n"
3291 "Connection: keep-alive\r\n\r\n"),
3292 };
3293
3294 MockRead data_reads[] = {
3295 MockRead("HTTP/1.1 200 OK\r\n"),
3296 MockRead("Content-Length: 11\r\n\r\n"),
3297 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3298 MockRead("hello world"),
3299 MockRead(true, 0, 0) // EOF
3300 };
3301
3302 SSLSocketDataProvider ssl(true, OK);
3303 SSLSocketDataProvider ssl2(true, OK);
3304 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3305 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3306
3307 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3308 data_writes, arraysize(data_writes));
3309 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3310 data_writes, arraysize(data_writes));
3311 session_deps.socket_factory.AddSocketDataProvider(&data);
3312 session_deps.socket_factory.AddSocketDataProvider(&data2);
3313
3314 TestCompletionCallback callback;
3315
3316 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3317 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3318
3319 int rv = trans->Start(&request, &callback, BoundNetLog());
3320
3321 EXPECT_EQ(ERR_IO_PENDING, rv);
3322 EXPECT_EQ(OK, callback.WaitForResult());
3323
3324 const HttpResponseInfo* response = trans->GetResponseInfo();
3325 ASSERT_TRUE(response != NULL);
3326 ASSERT_TRUE(response->headers != NULL);
3327 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3328
3329 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3330
3331 std::string response_data;
3332 rv = ReadTransaction(trans.get(), &response_data);
3333 EXPECT_EQ(OK, rv);
3334 EXPECT_EQ("hello world", response_data);
3335
3336 // Empty the current queue. This is necessary because idle sockets are
3337 // added to the connection pool asynchronously with a PostTask.
3338 MessageLoop::current()->RunAllPending();
3339
3340 // We now check to make sure the socket was added back to the pool.
3341 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3342
3343 // Now start the second transaction, which should reuse the previous socket.
3344
3345 trans.reset(new HttpNetworkTransaction(session));
3346
3347 rv = trans->Start(&request, &callback, BoundNetLog());
3348
3349 EXPECT_EQ(ERR_IO_PENDING, rv);
3350 EXPECT_EQ(OK, callback.WaitForResult());
3351
3352 response = trans->GetResponseInfo();
3353 ASSERT_TRUE(response != NULL);
3354 ASSERT_TRUE(response->headers != NULL);
3355 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3356
3357 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
3358
3359 rv = ReadTransaction(trans.get(), &response_data);
3360 EXPECT_EQ(OK, rv);
3361 EXPECT_EQ("hello world", response_data);
3362
3363 // Empty the current queue. This is necessary because idle sockets are
3364 // added to the connection pool asynchronously with a PostTask.
3365 MessageLoop::current()->RunAllPending();
3366
3367 // We now check to make sure the socket was added back to the pool.
3368 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3369}
3370
[email protected]b4404c02009-04-10 16:38:523371// Make sure that we recycle a socket after a zero-length response.
3372// http://crbug.com/9880
3373TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]228ff742009-06-05 01:19:593374 SessionDependencies session_deps;
3375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]b4404c02009-04-10 16:38:523376
[email protected]5695b8c2009-09-30 21:36:433377 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]b4404c02009-04-10 16:38:523378
[email protected]1c773ea12009-04-28 19:58:423379 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523380 request.method = "GET";
3381 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3382 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3383 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3384 "rt=prt.2642,ol.2649,xjs.2951");
3385 request.load_flags = 0;
3386
3387 MockRead data_reads[] = {
3388 MockRead("HTTP/1.1 204 No Content\r\n"
3389 "Content-Length: 0\r\n"
3390 "Content-Type: text/html\r\n\r\n"),
3391 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423392 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523393 };
3394
[email protected]31a2bfe2010-02-09 08:03:393395 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593396 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523397
3398 TestCompletionCallback callback;
3399
[email protected]5a1d7ca2010-04-28 20:12:273400 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423401 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523402
3403 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423404 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523405
[email protected]1c773ea12009-04-28 19:58:423406 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523407 EXPECT_TRUE(response != NULL);
3408
3409 EXPECT_TRUE(response->headers != NULL);
3410 std::string status_line = response->headers->GetStatusLine();
3411 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3412
[email protected]a937a06d2009-08-19 21:19:243413 EXPECT_EQ(0, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523414
3415 std::string response_data;
3416 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423417 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523418 EXPECT_EQ("", response_data);
3419
3420 // Empty the current queue. This is necessary because idle sockets are
3421 // added to the connection pool asynchronously with a PostTask.
3422 MessageLoop::current()->RunAllPending();
3423
3424 // We now check to make sure the socket was added back to the pool.
[email protected]a937a06d2009-08-19 21:19:243425 EXPECT_EQ(1, session->tcp_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523426}
3427
[email protected]372d34a2008-11-05 21:30:513428TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423429 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513430 // Transaction 1: a GET request that succeeds. The socket is recycled
3431 // after use.
3432 request[0].method = "GET";
3433 request[0].url = GURL("http://www.google.com/");
3434 request[0].load_flags = 0;
3435 // Transaction 2: a POST request. Reuses the socket kept alive from
3436 // transaction 1. The first attempts fails when writing the POST data.
3437 // This causes the transaction to retry with a new socket. The second
3438 // attempt succeeds.
3439 request[1].method = "POST";
3440 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423441 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513442 request[1].upload_data->AppendBytes("foo", 3);
3443 request[1].load_flags = 0;
3444
[email protected]228ff742009-06-05 01:19:593445 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273446 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513447
3448 // The first socket is used for transaction 1 and the first attempt of
3449 // transaction 2.
3450
3451 // The response of transaction 1.
3452 MockRead data_reads1[] = {
3453 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3454 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423455 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513456 };
3457 // The mock write results of transaction 1 and the first attempt of
3458 // transaction 2.
3459 MockWrite data_writes1[] = {
3460 MockWrite(false, 64), // GET
3461 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423462 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513463 };
[email protected]31a2bfe2010-02-09 08:03:393464 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3465 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513466
3467 // The second socket is used for the second attempt of transaction 2.
3468
3469 // The response of transaction 2.
3470 MockRead data_reads2[] = {
3471 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3472 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423473 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513474 };
3475 // The mock write results of the second attempt of transaction 2.
3476 MockWrite data_writes2[] = {
3477 MockWrite(false, 93), // POST
3478 MockWrite(false, 3), // POST data
3479 };
[email protected]31a2bfe2010-02-09 08:03:393480 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3481 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513482
[email protected]5ecc992a42009-11-11 01:41:593483 session_deps.socket_factory.AddSocketDataProvider(&data1);
3484 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513485
3486 const char* kExpectedResponseData[] = {
3487 "hello world", "welcome"
3488 };
3489
3490 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423491 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433492 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513493
3494 TestCompletionCallback callback;
3495
[email protected]5a1d7ca2010-04-28 20:12:273496 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423497 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513498
3499 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423500 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513501
[email protected]1c773ea12009-04-28 19:58:423502 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513503 EXPECT_TRUE(response != NULL);
3504
3505 EXPECT_TRUE(response->headers != NULL);
3506 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3507
3508 std::string response_data;
3509 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423510 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513511 EXPECT_EQ(kExpectedResponseData[i], response_data);
3512 }
3513}
[email protected]f9ee6b52008-11-08 06:46:233514
3515// Test the request-challenge-retry sequence for basic auth when there is
3516// an identity in the URL. The request should be sent as normal, but when
3517// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323518TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]228ff742009-06-05 01:19:593519 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:403520 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433521 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]f9ee6b52008-11-08 06:46:233522
[email protected]1c773ea12009-04-28 19:58:423523 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233524 request.method = "GET";
3525 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293526 request.url = GURL("http://foo:b@[email protected]/");
3527
3528 // The password contains an escaped character -- for this test to pass it
3529 // will need to be unescaped by HttpNetworkTransaction.
3530 EXPECT_EQ("b%40r", request.url.password());
3531
[email protected]ea9dc9a2009-09-05 00:43:323532 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233533
3534 MockWrite data_writes1[] = {
3535 MockWrite("GET / HTTP/1.1\r\n"
3536 "Host: www.google.com\r\n"
3537 "Connection: keep-alive\r\n\r\n"),
3538 };
3539
3540 MockRead data_reads1[] = {
3541 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3542 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3543 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423544 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233545 };
3546
3547 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323548 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233549 MockWrite data_writes2[] = {
3550 MockWrite("GET / HTTP/1.1\r\n"
3551 "Host: www.google.com\r\n"
3552 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293553 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233554 };
3555
3556 MockRead data_reads2[] = {
3557 MockRead("HTTP/1.0 200 OK\r\n"),
3558 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423559 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233560 };
3561
[email protected]31a2bfe2010-02-09 08:03:393562 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3563 data_writes1, arraysize(data_writes1));
3564 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3565 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593566 session_deps.socket_factory.AddSocketDataProvider(&data1);
3567 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233568
3569 TestCompletionCallback callback1;
3570
[email protected]5a1d7ca2010-04-28 20:12:273571 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423572 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233573
3574 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423575 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233576
[email protected]0757e7702009-03-27 04:00:223577 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3578 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443579 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423580 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223581 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423582 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223583 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3584
[email protected]1c773ea12009-04-28 19:58:423585 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233586 EXPECT_FALSE(response == NULL);
3587
3588 // There is no challenge info, since the identity in URL worked.
3589 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3590
3591 EXPECT_EQ(100, response->headers->GetContentLength());
3592
3593 // Empty the current queue.
3594 MessageLoop::current()->RunAllPending();
3595}
3596
[email protected]ea9dc9a2009-09-05 00:43:323597// Test the request-challenge-retry sequence for basic auth when there is
3598// an incorrect identity in the URL. The identity from the URL should be used
3599// only once.
3600TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
3601 SessionDependencies session_deps;
3602 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433603 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]ea9dc9a2009-09-05 00:43:323604
3605 HttpRequestInfo request;
3606 request.method = "GET";
3607 // Note: the URL has a username:password in it. The password "baz" is
3608 // wrong (should be "bar").
3609 request.url = GURL("http://foo:[email protected]/");
3610
3611 request.load_flags = LOAD_NORMAL;
3612
3613 MockWrite data_writes1[] = {
3614 MockWrite("GET / HTTP/1.1\r\n"
3615 "Host: www.google.com\r\n"
3616 "Connection: keep-alive\r\n\r\n"),
3617 };
3618
3619 MockRead data_reads1[] = {
3620 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3621 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3622 MockRead("Content-Length: 10\r\n\r\n"),
3623 MockRead(false, ERR_FAILED),
3624 };
3625
3626 // After the challenge above, the transaction will be restarted using the
3627 // identity from the url (foo, baz) to answer the challenge.
3628 MockWrite data_writes2[] = {
3629 MockWrite("GET / HTTP/1.1\r\n"
3630 "Host: www.google.com\r\n"
3631 "Connection: keep-alive\r\n"
3632 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3633 };
3634
3635 MockRead data_reads2[] = {
3636 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3637 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3638 MockRead("Content-Length: 10\r\n\r\n"),
3639 MockRead(false, ERR_FAILED),
3640 };
3641
3642 // After the challenge above, the transaction will be restarted using the
3643 // identity supplied by the user (foo, bar) to answer the challenge.
3644 MockWrite data_writes3[] = {
3645 MockWrite("GET / HTTP/1.1\r\n"
3646 "Host: www.google.com\r\n"
3647 "Connection: keep-alive\r\n"
3648 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3649 };
3650
3651 MockRead data_reads3[] = {
3652 MockRead("HTTP/1.0 200 OK\r\n"),
3653 MockRead("Content-Length: 100\r\n\r\n"),
3654 MockRead(false, OK),
3655 };
3656
[email protected]31a2bfe2010-02-09 08:03:393657 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3658 data_writes1, arraysize(data_writes1));
3659 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3660 data_writes2, arraysize(data_writes2));
3661 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3662 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593663 session_deps.socket_factory.AddSocketDataProvider(&data1);
3664 session_deps.socket_factory.AddSocketDataProvider(&data2);
3665 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323666
3667 TestCompletionCallback callback1;
3668
[email protected]5a1d7ca2010-04-28 20:12:273669 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323670 EXPECT_EQ(ERR_IO_PENDING, rv);
3671
3672 rv = callback1.WaitForResult();
3673 EXPECT_EQ(OK, rv);
3674
3675 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3676 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443677 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323678 EXPECT_EQ(ERR_IO_PENDING, rv);
3679 rv = callback2.WaitForResult();
3680 EXPECT_EQ(OK, rv);
3681 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3682
3683 const HttpResponseInfo* response = trans->GetResponseInfo();
3684 EXPECT_FALSE(response == NULL);
3685 // The password prompt info should have been set in response->auth_challenge.
3686 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3687
3688 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3689 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3690 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3691
3692 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443693 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323694 EXPECT_EQ(ERR_IO_PENDING, rv);
3695 rv = callback3.WaitForResult();
3696 EXPECT_EQ(OK, rv);
3697 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3698
3699 response = trans->GetResponseInfo();
3700 EXPECT_FALSE(response == NULL);
3701
3702 // There is no challenge info, since the identity worked.
3703 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3704
3705 EXPECT_EQ(100, response->headers->GetContentLength());
3706
3707 // Empty the current queue.
3708 MessageLoop::current()->RunAllPending();
3709}
3710
[email protected]f9ee6b52008-11-08 06:46:233711// Test that previously tried username/passwords for a realm get re-used.
3712TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593713 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273714 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233715
3716 // Transaction 1: authenticate (foo, bar) on MyRealm1
3717 {
[email protected]5695b8c2009-09-30 21:36:433718 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233719
[email protected]1c773ea12009-04-28 19:58:423720 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233721 request.method = "GET";
3722 request.url = GURL("http://www.google.com/x/y/z");
3723 request.load_flags = 0;
3724
3725 MockWrite data_writes1[] = {
3726 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3727 "Host: www.google.com\r\n"
3728 "Connection: keep-alive\r\n\r\n"),
3729 };
3730
3731 MockRead data_reads1[] = {
3732 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3733 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3734 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423735 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233736 };
3737
3738 // Resend with authorization (username=foo, password=bar)
3739 MockWrite data_writes2[] = {
3740 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3741 "Host: www.google.com\r\n"
3742 "Connection: keep-alive\r\n"
3743 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3744 };
3745
3746 // Sever accepts the authorization.
3747 MockRead data_reads2[] = {
3748 MockRead("HTTP/1.0 200 OK\r\n"),
3749 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423750 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233751 };
3752
[email protected]31a2bfe2010-02-09 08:03:393753 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3754 data_writes1, arraysize(data_writes1));
3755 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3756 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593757 session_deps.socket_factory.AddSocketDataProvider(&data1);
3758 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233759
3760 TestCompletionCallback callback1;
3761
[email protected]5a1d7ca2010-04-28 20:12:273762 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423763 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233764
3765 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423766 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233767
[email protected]1c773ea12009-04-28 19:58:423768 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233769 EXPECT_FALSE(response == NULL);
3770
3771 // The password prompt info should have been set in
3772 // response->auth_challenge.
3773 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3774
[email protected]71e4573a2009-05-21 22:03:003775 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233776 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3777 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3778
3779 TestCompletionCallback callback2;
3780
[email protected]13c8a092010-07-29 06:15:443781 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423782 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233783
3784 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423785 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233786
3787 response = trans->GetResponseInfo();
3788 EXPECT_FALSE(response == NULL);
3789 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3790 EXPECT_EQ(100, response->headers->GetContentLength());
3791 }
3792
3793 // ------------------------------------------------------------------------
3794
3795 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3796 {
[email protected]5695b8c2009-09-30 21:36:433797 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233798
[email protected]1c773ea12009-04-28 19:58:423799 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233800 request.method = "GET";
3801 // Note that Transaction 1 was at /x/y/z, so this is in the same
3802 // protection space as MyRealm1.
3803 request.url = GURL("http://www.google.com/x/y/a/b");
3804 request.load_flags = 0;
3805
3806 MockWrite data_writes1[] = {
3807 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3808 "Host: www.google.com\r\n"
3809 "Connection: keep-alive\r\n"
3810 // Send preemptive authorization for MyRealm1
3811 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3812 };
3813
3814 // The server didn't like the preemptive authorization, and
3815 // challenges us for a different realm (MyRealm2).
3816 MockRead data_reads1[] = {
3817 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3818 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3819 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423820 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233821 };
3822
3823 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3824 MockWrite data_writes2[] = {
3825 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3826 "Host: www.google.com\r\n"
3827 "Connection: keep-alive\r\n"
3828 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3829 };
3830
3831 // Sever accepts the authorization.
3832 MockRead data_reads2[] = {
3833 MockRead("HTTP/1.0 200 OK\r\n"),
3834 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423835 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233836 };
3837
[email protected]31a2bfe2010-02-09 08:03:393838 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3839 data_writes1, arraysize(data_writes1));
3840 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3841 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593842 session_deps.socket_factory.AddSocketDataProvider(&data1);
3843 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233844
3845 TestCompletionCallback callback1;
3846
[email protected]5a1d7ca2010-04-28 20:12:273847 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423848 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233849
3850 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423851 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233852
[email protected]1c773ea12009-04-28 19:58:423853 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233854 EXPECT_FALSE(response == NULL);
3855
3856 // The password prompt info should have been set in
3857 // response->auth_challenge.
3858 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3859
[email protected]71e4573a2009-05-21 22:03:003860 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233861 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3862 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3863
3864 TestCompletionCallback callback2;
3865
[email protected]13c8a092010-07-29 06:15:443866 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423867 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233868
3869 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423870 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233871
3872 response = trans->GetResponseInfo();
3873 EXPECT_FALSE(response == NULL);
3874 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3875 EXPECT_EQ(100, response->headers->GetContentLength());
3876 }
3877
3878 // ------------------------------------------------------------------------
3879
3880 // Transaction 3: Resend a request in MyRealm's protection space --
3881 // succeed with preemptive authorization.
3882 {
[email protected]5695b8c2009-09-30 21:36:433883 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233884
[email protected]1c773ea12009-04-28 19:58:423885 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233886 request.method = "GET";
3887 request.url = GURL("http://www.google.com/x/y/z2");
3888 request.load_flags = 0;
3889
3890 MockWrite data_writes1[] = {
3891 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3892 "Host: www.google.com\r\n"
3893 "Connection: keep-alive\r\n"
3894 // The authorization for MyRealm1 gets sent preemptively
3895 // (since the url is in the same protection space)
3896 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3897 };
3898
3899 // Sever accepts the preemptive authorization
3900 MockRead data_reads1[] = {
3901 MockRead("HTTP/1.0 200 OK\r\n"),
3902 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423903 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233904 };
3905
[email protected]31a2bfe2010-02-09 08:03:393906 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3907 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593908 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233909
3910 TestCompletionCallback callback1;
3911
[email protected]5a1d7ca2010-04-28 20:12:273912 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423913 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233914
3915 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423916 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233917
[email protected]1c773ea12009-04-28 19:58:423918 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233919 EXPECT_FALSE(response == NULL);
3920
3921 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3922 EXPECT_EQ(100, response->headers->GetContentLength());
3923 }
3924
3925 // ------------------------------------------------------------------------
3926
3927 // Transaction 4: request another URL in MyRealm (however the
3928 // url is not known to belong to the protection space, so no pre-auth).
3929 {
[email protected]5695b8c2009-09-30 21:36:433930 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:233931
[email protected]1c773ea12009-04-28 19:58:423932 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233933 request.method = "GET";
3934 request.url = GURL("http://www.google.com/x/1");
3935 request.load_flags = 0;
3936
3937 MockWrite data_writes1[] = {
3938 MockWrite("GET /x/1 HTTP/1.1\r\n"
3939 "Host: www.google.com\r\n"
3940 "Connection: keep-alive\r\n\r\n"),
3941 };
3942
3943 MockRead data_reads1[] = {
3944 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3945 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3946 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423947 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233948 };
3949
3950 // Resend with authorization from MyRealm's cache.
3951 MockWrite data_writes2[] = {
3952 MockWrite("GET /x/1 HTTP/1.1\r\n"
3953 "Host: www.google.com\r\n"
3954 "Connection: keep-alive\r\n"
3955 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3956 };
3957
3958 // Sever accepts the authorization.
3959 MockRead data_reads2[] = {
3960 MockRead("HTTP/1.0 200 OK\r\n"),
3961 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423962 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233963 };
3964
[email protected]31a2bfe2010-02-09 08:03:393965 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3966 data_writes1, arraysize(data_writes1));
3967 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3968 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593969 session_deps.socket_factory.AddSocketDataProvider(&data1);
3970 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233971
3972 TestCompletionCallback callback1;
3973
[email protected]5a1d7ca2010-04-28 20:12:273974 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423975 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233976
3977 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423978 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233979
[email protected]0757e7702009-03-27 04:00:223980 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3981 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443982 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223984 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423985 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223986 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3987
[email protected]1c773ea12009-04-28 19:58:423988 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233989 EXPECT_FALSE(response == NULL);
3990 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3991 EXPECT_EQ(100, response->headers->GetContentLength());
3992 }
3993
3994 // ------------------------------------------------------------------------
3995
3996 // Transaction 5: request a URL in MyRealm, but the server rejects the
3997 // cached identity. Should invalidate and re-prompt.
3998 {
[email protected]5695b8c2009-09-30 21:36:433999 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f9ee6b52008-11-08 06:46:234000
[email protected]1c773ea12009-04-28 19:58:424001 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234002 request.method = "GET";
4003 request.url = GURL("http://www.google.com/p/q/t");
4004 request.load_flags = 0;
4005
4006 MockWrite data_writes1[] = {
4007 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4008 "Host: www.google.com\r\n"
4009 "Connection: keep-alive\r\n\r\n"),
4010 };
4011
4012 MockRead data_reads1[] = {
4013 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4014 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4015 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424016 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234017 };
4018
4019 // Resend with authorization from cache for MyRealm.
4020 MockWrite data_writes2[] = {
4021 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4022 "Host: www.google.com\r\n"
4023 "Connection: keep-alive\r\n"
4024 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4025 };
4026
4027 // Sever rejects the authorization.
4028 MockRead data_reads2[] = {
4029 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4030 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4031 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424032 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234033 };
4034
4035 // At this point we should prompt for new credentials for MyRealm.
4036 // Restart with username=foo3, password=foo4.
4037 MockWrite data_writes3[] = {
4038 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4039 "Host: www.google.com\r\n"
4040 "Connection: keep-alive\r\n"
4041 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4042 };
4043
4044 // Sever accepts the authorization.
4045 MockRead data_reads3[] = {
4046 MockRead("HTTP/1.0 200 OK\r\n"),
4047 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424048 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234049 };
4050
[email protected]31a2bfe2010-02-09 08:03:394051 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4052 data_writes1, arraysize(data_writes1));
4053 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4054 data_writes2, arraysize(data_writes2));
4055 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4056 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594057 session_deps.socket_factory.AddSocketDataProvider(&data1);
4058 session_deps.socket_factory.AddSocketDataProvider(&data2);
4059 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234060
4061 TestCompletionCallback callback1;
4062
[email protected]5a1d7ca2010-04-28 20:12:274063 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424064 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234065
4066 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424067 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234068
[email protected]0757e7702009-03-27 04:00:224069 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4070 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444071 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424072 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224073 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424074 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224075 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4076
[email protected]1c773ea12009-04-28 19:58:424077 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234078 EXPECT_FALSE(response == NULL);
4079
4080 // The password prompt info should have been set in
4081 // response->auth_challenge.
4082 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4083
[email protected]71e4573a2009-05-21 22:03:004084 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234085 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4086 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4087
[email protected]0757e7702009-03-27 04:00:224088 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234089
[email protected]13c8a092010-07-29 06:15:444090 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424091 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234092
[email protected]0757e7702009-03-27 04:00:224093 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424094 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234095
4096 response = trans->GetResponseInfo();
4097 EXPECT_FALSE(response == NULL);
4098 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4099 EXPECT_EQ(100, response->headers->GetContentLength());
4100 }
4101}
[email protected]89ceba9a2009-03-21 03:46:064102
[email protected]3c32c5f2010-05-18 15:18:124103// Tests that nonce count increments when multiple auth attempts
4104// are started with the same nonce.
4105TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4106 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444107 HttpAuthHandlerDigest::Factory* digest_factory =
4108 new HttpAuthHandlerDigest::Factory();
4109 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4110 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4111 digest_factory->set_nonce_generator(nonce_generator);
4112 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274113 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124114
4115 // Transaction 1: authenticate (foo, bar) on MyRealm1
4116 {
4117 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4118
4119 HttpRequestInfo request;
4120 request.method = "GET";
4121 request.url = GURL("http://www.google.com/x/y/z");
4122 request.load_flags = 0;
4123
4124 MockWrite data_writes1[] = {
4125 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4126 "Host: www.google.com\r\n"
4127 "Connection: keep-alive\r\n\r\n"),
4128 };
4129
4130 MockRead data_reads1[] = {
4131 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4132 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4133 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4134 MockRead(false, OK),
4135 };
4136
4137 // Resend with authorization (username=foo, password=bar)
4138 MockWrite data_writes2[] = {
4139 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4140 "Host: www.google.com\r\n"
4141 "Connection: keep-alive\r\n"
4142 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4143 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4144 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4145 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4146 };
4147
4148 // Sever accepts the authorization.
4149 MockRead data_reads2[] = {
4150 MockRead("HTTP/1.0 200 OK\r\n"),
4151 MockRead(false, OK),
4152 };
4153
4154 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4155 data_writes1, arraysize(data_writes1));
4156 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4157 data_writes2, arraysize(data_writes2));
4158 session_deps.socket_factory.AddSocketDataProvider(&data1);
4159 session_deps.socket_factory.AddSocketDataProvider(&data2);
4160
4161 TestCompletionCallback callback1;
4162
4163 int rv = trans->Start(&request, &callback1, BoundNetLog());
4164 EXPECT_EQ(ERR_IO_PENDING, rv);
4165
4166 rv = callback1.WaitForResult();
4167 EXPECT_EQ(OK, rv);
4168
4169 const HttpResponseInfo* response = trans->GetResponseInfo();
4170 ASSERT_FALSE(response == NULL);
4171
4172 // The password prompt info should have been set in
4173 // response->auth_challenge.
4174 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4175
4176 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4177 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4178 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4179
4180 TestCompletionCallback callback2;
4181
[email protected]13c8a092010-07-29 06:15:444182 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124183 EXPECT_EQ(ERR_IO_PENDING, rv);
4184
4185 rv = callback2.WaitForResult();
4186 EXPECT_EQ(OK, rv);
4187
4188 response = trans->GetResponseInfo();
4189 ASSERT_FALSE(response == NULL);
4190 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4191 }
4192
4193 // ------------------------------------------------------------------------
4194
4195 // Transaction 2: Request another resource in digestive's protection space.
4196 // This will preemptively add an Authorization header which should have an
4197 // "nc" value of 2 (as compared to 1 in the first use.
4198 {
4199 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4200
4201 HttpRequestInfo request;
4202 request.method = "GET";
4203 // Note that Transaction 1 was at /x/y/z, so this is in the same
4204 // protection space as digest.
4205 request.url = GURL("http://www.google.com/x/y/a/b");
4206 request.load_flags = 0;
4207
4208 MockWrite data_writes1[] = {
4209 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4210 "Host: www.google.com\r\n"
4211 "Connection: keep-alive\r\n"
4212 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4213 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4214 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4215 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4216 };
4217
4218 // Sever accepts the authorization.
4219 MockRead data_reads1[] = {
4220 MockRead("HTTP/1.0 200 OK\r\n"),
4221 MockRead("Content-Length: 100\r\n\r\n"),
4222 MockRead(false, OK),
4223 };
4224
4225 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4226 data_writes1, arraysize(data_writes1));
4227 session_deps.socket_factory.AddSocketDataProvider(&data1);
4228
4229 TestCompletionCallback callback1;
4230
4231 int rv = trans->Start(&request, &callback1, BoundNetLog());
4232 EXPECT_EQ(ERR_IO_PENDING, rv);
4233
4234 rv = callback1.WaitForResult();
4235 EXPECT_EQ(OK, rv);
4236
4237 const HttpResponseInfo* response = trans->GetResponseInfo();
4238 ASSERT_FALSE(response == NULL);
4239 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4240 }
4241}
4242
[email protected]89ceba9a2009-03-21 03:46:064243// Test the ResetStateForRestart() private method.
4244TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4245 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594246 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404247 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434248 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064249
4250 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064251 trans->read_buf_ = new IOBuffer(15);
4252 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204253 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064254
4255 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144256 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574257 response->auth_challenge = new AuthChallengeInfo();
4258 response->ssl_info.cert_status = -15;
4259 response->response_time = base::Time::Now();
4260 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064261
4262 { // Setup state for response_.vary_data
4263 HttpRequestInfo request;
4264 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4265 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274266 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434267 request.extra_headers.SetHeader("Foo", "1");
4268 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574269 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064270 }
4271
4272 // Cause the above state to be reset.
4273 trans->ResetStateForRestart();
4274
4275 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074276 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064277 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204278 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574279 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4280 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044281 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574282 EXPECT_EQ(0, response->ssl_info.cert_status);
4283 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064284}
4285
[email protected]bacff652009-03-31 17:50:334286// Test HTTPS connections to a site with a bad certificate
4287TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]228ff742009-06-05 01:19:594288 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404289 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434290 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334291
4292 HttpRequestInfo request;
4293 request.method = "GET";
4294 request.url = GURL("https://www.google.com/");
4295 request.load_flags = 0;
4296
4297 MockWrite data_writes[] = {
4298 MockWrite("GET / HTTP/1.1\r\n"
4299 "Host: www.google.com\r\n"
4300 "Connection: keep-alive\r\n\r\n"),
4301 };
4302
4303 MockRead data_reads[] = {
4304 MockRead("HTTP/1.0 200 OK\r\n"),
4305 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4306 MockRead("Content-Length: 100\r\n\r\n"),
4307 MockRead(false, OK),
4308 };
4309
[email protected]5ecc992a42009-11-11 01:41:594310 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394311 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4312 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594313 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4314 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334315
[email protected]5ecc992a42009-11-11 01:41:594316 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4317 session_deps.socket_factory.AddSocketDataProvider(&data);
4318 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4319 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334320
4321 TestCompletionCallback callback;
4322
[email protected]5a1d7ca2010-04-28 20:12:274323 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334324 EXPECT_EQ(ERR_IO_PENDING, rv);
4325
4326 rv = callback.WaitForResult();
4327 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4328
4329 rv = trans->RestartIgnoringLastError(&callback);
4330 EXPECT_EQ(ERR_IO_PENDING, rv);
4331
4332 rv = callback.WaitForResult();
4333 EXPECT_EQ(OK, rv);
4334
4335 const HttpResponseInfo* response = trans->GetResponseInfo();
4336
4337 EXPECT_FALSE(response == NULL);
4338 EXPECT_EQ(100, response->headers->GetContentLength());
4339}
4340
4341// Test HTTPS connections to a site with a bad certificate, going through a
4342// proxy
4343TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004344 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334345
4346 HttpRequestInfo request;
4347 request.method = "GET";
4348 request.url = GURL("https://www.google.com/");
4349 request.load_flags = 0;
4350
4351 MockWrite proxy_writes[] = {
4352 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454353 "Host: www.google.com\r\n"
4354 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334355 };
4356
4357 MockRead proxy_reads[] = {
4358 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424359 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334360 };
4361
4362 MockWrite data_writes[] = {
4363 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454364 "Host: www.google.com\r\n"
4365 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334366 MockWrite("GET / HTTP/1.1\r\n"
4367 "Host: www.google.com\r\n"
4368 "Connection: keep-alive\r\n\r\n"),
4369 };
4370
4371 MockRead data_reads[] = {
4372 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4373 MockRead("HTTP/1.0 200 OK\r\n"),
4374 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4375 MockRead("Content-Length: 100\r\n\r\n"),
4376 MockRead(false, OK),
4377 };
4378
[email protected]31a2bfe2010-02-09 08:03:394379 StaticSocketDataProvider ssl_bad_certificate(
4380 proxy_reads, arraysize(proxy_reads),
4381 proxy_writes, arraysize(proxy_writes));
4382 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4383 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594384 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4385 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334386
[email protected]5ecc992a42009-11-11 01:41:594387 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4388 session_deps.socket_factory.AddSocketDataProvider(&data);
4389 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4390 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334391
4392 TestCompletionCallback callback;
4393
4394 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594395 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334396
[email protected]d207a5f2009-06-04 05:28:404397 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434398 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334399
[email protected]5a1d7ca2010-04-28 20:12:274400 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334401 EXPECT_EQ(ERR_IO_PENDING, rv);
4402
4403 rv = callback.WaitForResult();
4404 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4405
4406 rv = trans->RestartIgnoringLastError(&callback);
4407 EXPECT_EQ(ERR_IO_PENDING, rv);
4408
4409 rv = callback.WaitForResult();
4410 EXPECT_EQ(OK, rv);
4411
4412 const HttpResponseInfo* response = trans->GetResponseInfo();
4413
4414 EXPECT_FALSE(response == NULL);
4415 EXPECT_EQ(100, response->headers->GetContentLength());
4416 }
4417}
4418
[email protected]2df19bb2010-08-25 20:13:464419
4420// Test HTTPS connections to a site, going through an HTTPS proxy
4421TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004422 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464423
4424 HttpRequestInfo request;
4425 request.method = "GET";
4426 request.url = GURL("https://www.google.com/");
4427 request.load_flags = 0;
4428
4429 MockWrite data_writes[] = {
4430 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4431 "Host: www.google.com\r\n"
4432 "Proxy-Connection: keep-alive\r\n\r\n"),
4433 MockWrite("GET / HTTP/1.1\r\n"
4434 "Host: www.google.com\r\n"
4435 "Connection: keep-alive\r\n\r\n"),
4436 };
4437
4438 MockRead data_reads[] = {
4439 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4440 MockRead("HTTP/1.1 200 OK\r\n"),
4441 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4442 MockRead("Content-Length: 100\r\n\r\n"),
4443 MockRead(false, OK),
4444 };
4445
4446 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4447 data_writes, arraysize(data_writes));
4448 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4449 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4450
4451 session_deps.socket_factory.AddSocketDataProvider(&data);
4452 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4453 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4454
4455 TestCompletionCallback callback;
4456
4457 scoped_ptr<HttpTransaction> trans(
4458 new HttpNetworkTransaction(CreateSession(&session_deps)));
4459
4460 int rv = trans->Start(&request, &callback, BoundNetLog());
4461 EXPECT_EQ(ERR_IO_PENDING, rv);
4462
4463 rv = callback.WaitForResult();
4464 EXPECT_EQ(OK, rv);
4465 const HttpResponseInfo* response = trans->GetResponseInfo();
4466
4467 ASSERT_FALSE(response == NULL);
4468
4469 EXPECT_TRUE(response->headers->IsKeepAlive());
4470 EXPECT_EQ(200, response->headers->response_code());
4471 EXPECT_EQ(100, response->headers->GetContentLength());
4472 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4473}
4474
[email protected]511f6f52010-12-17 03:58:294475// Test an HTTPS Proxy's ability to redirect a CONNECT request
4476TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4477 SessionDependencies session_deps(
4478 ProxyService::CreateFixed("https://proxy:70"));
4479
4480 HttpRequestInfo request;
4481 request.method = "GET";
4482 request.url = GURL("https://www.google.com/");
4483 request.load_flags = 0;
4484
4485 MockWrite data_writes[] = {
4486 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4487 "Host: www.google.com\r\n"
4488 "Proxy-Connection: keep-alive\r\n\r\n"),
4489 };
4490
4491 MockRead data_reads[] = {
4492 MockRead("HTTP/1.1 302 Redirect\r\n"),
4493 MockRead("Location: http://login.example.com/\r\n"),
4494 MockRead("Content-Length: 0\r\n\r\n"),
4495 MockRead(false, OK),
4496 };
4497
4498 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4499 data_writes, arraysize(data_writes));
4500 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4501
4502 session_deps.socket_factory.AddSocketDataProvider(&data);
4503 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4504
4505 TestCompletionCallback callback;
4506
4507 scoped_ptr<HttpTransaction> trans(
4508 new HttpNetworkTransaction(CreateSession(&session_deps)));
4509
4510 int rv = trans->Start(&request, &callback, BoundNetLog());
4511 EXPECT_EQ(ERR_IO_PENDING, rv);
4512
4513 rv = callback.WaitForResult();
4514 EXPECT_EQ(OK, rv);
4515 const HttpResponseInfo* response = trans->GetResponseInfo();
4516
4517 ASSERT_FALSE(response == NULL);
4518
4519 EXPECT_EQ(302, response->headers->response_code());
4520 std::string url;
4521 EXPECT_TRUE(response->headers->IsRedirect(&url));
4522 EXPECT_EQ("http://login.example.com/", url);
4523}
4524
4525// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4526TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4527 SessionDependencies session_deps(
4528 ProxyService::CreateFixed("https://proxy:70"));
4529
4530 HttpRequestInfo request;
4531 request.method = "GET";
4532 request.url = GURL("https://www.google.com/");
4533 request.load_flags = 0;
4534
4535 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4536 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4537 MockWrite data_writes[] = {
4538 CreateMockWrite(*conn.get(), 0, false),
4539 };
4540
4541 static const char* const kExtraHeaders[] = {
4542 "location",
4543 "http://login.example.com/",
4544 };
4545 scoped_ptr<spdy::SpdyFrame> resp(
4546 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4547 arraysize(kExtraHeaders)/2, 1));
4548 MockRead data_reads[] = {
4549 CreateMockRead(*resp.get(), 1, false),
4550 MockRead(true, 0, 2), // EOF
4551 };
4552
4553 scoped_refptr<DelayedSocketData> data(
4554 new DelayedSocketData(
4555 1, // wait for one write to finish before reading.
4556 data_reads, arraysize(data_reads),
4557 data_writes, arraysize(data_writes)));
4558 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4559 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4560 proxy_ssl.next_proto = "spdy/2";
4561 proxy_ssl.was_npn_negotiated = true;
4562
4563 session_deps.socket_factory.AddSocketDataProvider(data.get());
4564 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4565
4566 TestCompletionCallback callback;
4567
4568 scoped_ptr<HttpTransaction> trans(
4569 new HttpNetworkTransaction(CreateSession(&session_deps)));
4570
4571 int rv = trans->Start(&request, &callback, BoundNetLog());
4572 EXPECT_EQ(ERR_IO_PENDING, rv);
4573
4574 rv = callback.WaitForResult();
4575 EXPECT_EQ(OK, rv);
4576 const HttpResponseInfo* response = trans->GetResponseInfo();
4577
4578 ASSERT_FALSE(response == NULL);
4579
4580 EXPECT_EQ(302, response->headers->response_code());
4581 std::string url;
4582 EXPECT_TRUE(response->headers->IsRedirect(&url));
4583 EXPECT_EQ("http://login.example.com/", url);
4584}
4585
4586// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4587TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4588 SessionDependencies session_deps(
4589 ProxyService::CreateFixed("https://proxy:70"));
4590
4591 HttpRequestInfo request;
4592 request.method = "GET";
4593 request.url = GURL("https://www.google.com/");
4594 request.load_flags = 0;
4595
4596 MockWrite data_writes[] = {
4597 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4598 "Host: www.google.com\r\n"
4599 "Proxy-Connection: keep-alive\r\n\r\n"),
4600 };
4601
4602 MockRead data_reads[] = {
4603 MockRead("HTTP/1.1 404 Not Found\r\n"),
4604 MockRead("Content-Length: 23\r\n\r\n"),
4605 MockRead("The host does not exist"),
4606 MockRead(false, OK),
4607 };
4608
4609 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4610 data_writes, arraysize(data_writes));
4611 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4612
4613 session_deps.socket_factory.AddSocketDataProvider(&data);
4614 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4615
4616 TestCompletionCallback callback;
4617
4618 scoped_ptr<HttpTransaction> trans(
4619 new HttpNetworkTransaction(CreateSession(&session_deps)));
4620
4621 int rv = trans->Start(&request, &callback, BoundNetLog());
4622 EXPECT_EQ(ERR_IO_PENDING, rv);
4623
4624 rv = callback.WaitForResult();
4625 EXPECT_EQ(OK, rv);
4626 const HttpResponseInfo* response = trans->GetResponseInfo();
4627
4628 ASSERT_FALSE(response == NULL);
4629
4630 EXPECT_EQ(404, response->headers->response_code());
4631 EXPECT_EQ(23, response->headers->GetContentLength());
4632 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4633 EXPECT_FALSE(response->ssl_info.is_valid());
4634
4635 std::string response_data;
4636 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4637 EXPECT_EQ("The host does not exist", response_data);
4638}
4639
4640// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4641// request
4642TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4643 SessionDependencies session_deps(
4644 ProxyService::CreateFixed("https://proxy:70"));
4645
4646 HttpRequestInfo request;
4647 request.method = "GET";
4648 request.url = GURL("https://www.google.com/");
4649 request.load_flags = 0;
4650
4651 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4652 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4653 MockWrite data_writes[] = {
4654 CreateMockWrite(*conn.get(), 0, false),
4655 };
4656
4657 static const char* const kExtraHeaders[] = {
4658 "location",
4659 "http://login.example.com/",
4660 };
4661 scoped_ptr<spdy::SpdyFrame> resp(
4662 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4663 arraysize(kExtraHeaders)/2, 1));
4664 scoped_ptr<spdy::SpdyFrame> body(
4665 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4666 MockRead data_reads[] = {
4667 CreateMockRead(*resp.get(), 1, false),
4668 CreateMockRead(*body.get(), 2, false),
4669 MockRead(true, 0, 3), // EOF
4670 };
4671
4672 scoped_refptr<DelayedSocketData> data(
4673 new DelayedSocketData(
4674 1, // wait for one write to finish before reading.
4675 data_reads, arraysize(data_reads),
4676 data_writes, arraysize(data_writes)));
4677 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4678 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4679 proxy_ssl.next_proto = "spdy/2";
4680 proxy_ssl.was_npn_negotiated = true;
4681
4682 session_deps.socket_factory.AddSocketDataProvider(data.get());
4683 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4684
4685 TestCompletionCallback callback;
4686
4687 scoped_ptr<HttpTransaction> trans(
4688 new HttpNetworkTransaction(CreateSession(&session_deps)));
4689
4690 int rv = trans->Start(&request, &callback, BoundNetLog());
4691 EXPECT_EQ(ERR_IO_PENDING, rv);
4692
4693 rv = callback.WaitForResult();
4694 EXPECT_EQ(OK, rv);
4695 const HttpResponseInfo* response = trans->GetResponseInfo();
4696
4697 ASSERT_FALSE(response == NULL);
4698
4699 EXPECT_EQ(404, response->headers->response_code());
4700 EXPECT_FALSE(response->ssl_info.is_valid());
4701
4702 std::string response_data;
4703 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4704 EXPECT_EQ("The host does not exist", response_data);
4705}
4706
[email protected]2df19bb2010-08-25 20:13:464707// Test HTTPS connections to a site with a bad certificate, going through an
4708// HTTPS proxy
4709TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004710 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464711
4712 HttpRequestInfo request;
4713 request.method = "GET";
4714 request.url = GURL("https://www.google.com/");
4715 request.load_flags = 0;
4716
4717 // Attempt to fetch the URL from a server with a bad cert
4718 MockWrite bad_cert_writes[] = {
4719 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4720 "Host: www.google.com\r\n"
4721 "Proxy-Connection: keep-alive\r\n\r\n"),
4722 };
4723
4724 MockRead bad_cert_reads[] = {
4725 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4726 MockRead(false, OK)
4727 };
4728
4729 // Attempt to fetch the URL with a good cert
4730 MockWrite good_data_writes[] = {
4731 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4732 "Host: www.google.com\r\n"
4733 "Proxy-Connection: keep-alive\r\n\r\n"),
4734 MockWrite("GET / HTTP/1.1\r\n"
4735 "Host: www.google.com\r\n"
4736 "Connection: keep-alive\r\n\r\n"),
4737 };
4738
4739 MockRead good_cert_reads[] = {
4740 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4741 MockRead("HTTP/1.0 200 OK\r\n"),
4742 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4743 MockRead("Content-Length: 100\r\n\r\n"),
4744 MockRead(false, OK),
4745 };
4746
4747 StaticSocketDataProvider ssl_bad_certificate(
4748 bad_cert_reads, arraysize(bad_cert_reads),
4749 bad_cert_writes, arraysize(bad_cert_writes));
4750 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4751 good_data_writes, arraysize(good_data_writes));
4752 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4753 SSLSocketDataProvider ssl(true, OK);
4754
4755 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4756 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4757 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4758 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4759
4760 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4761 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4762 session_deps.socket_factory.AddSocketDataProvider(&data);
4763 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4764
4765 TestCompletionCallback callback;
4766
4767 scoped_ptr<HttpTransaction> trans(
4768 new HttpNetworkTransaction(CreateSession(&session_deps)));
4769
4770 int rv = trans->Start(&request, &callback, BoundNetLog());
4771 EXPECT_EQ(ERR_IO_PENDING, rv);
4772
4773 rv = callback.WaitForResult();
4774 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4775
4776 rv = trans->RestartIgnoringLastError(&callback);
4777 EXPECT_EQ(ERR_IO_PENDING, rv);
4778
4779 rv = callback.WaitForResult();
4780 EXPECT_EQ(OK, rv);
4781
4782 const HttpResponseInfo* response = trans->GetResponseInfo();
4783
4784 EXPECT_FALSE(response == NULL);
4785 EXPECT_EQ(100, response->headers->GetContentLength());
4786}
4787
[email protected]1c773ea12009-04-28 19:58:424788TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]228ff742009-06-05 01:19:594789 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404790 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434791 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424792
4793 HttpRequestInfo request;
4794 request.method = "GET";
4795 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434796 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4797 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424798
4799 MockWrite data_writes[] = {
4800 MockWrite("GET / HTTP/1.1\r\n"
4801 "Host: www.google.com\r\n"
4802 "Connection: keep-alive\r\n"
4803 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4804 };
4805
4806 // Lastly, the server responds with the actual content.
4807 MockRead data_reads[] = {
4808 MockRead("HTTP/1.0 200 OK\r\n"),
4809 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4810 MockRead("Content-Length: 100\r\n\r\n"),
4811 MockRead(false, OK),
4812 };
4813
[email protected]31a2bfe2010-02-09 08:03:394814 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4815 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594816 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424817
4818 TestCompletionCallback callback;
4819
[email protected]5a1d7ca2010-04-28 20:12:274820 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424821 EXPECT_EQ(ERR_IO_PENDING, rv);
4822
4823 rv = callback.WaitForResult();
4824 EXPECT_EQ(OK, rv);
4825}
4826
[email protected]da81f132010-08-18 23:39:294827TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]81cdfcd2010-10-16 00:49:004828 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]da81f132010-08-18 23:39:294829 scoped_ptr<HttpTransaction> trans(
4830 new HttpNetworkTransaction(CreateSession(&session_deps)));
4831
4832 HttpRequestInfo request;
4833 request.method = "GET";
4834 request.url = GURL("https://www.google.com/");
4835 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4836 "Chromium Ultra Awesome X Edition");
4837
4838 MockWrite data_writes[] = {
4839 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4840 "Host: www.google.com\r\n"
4841 "Proxy-Connection: keep-alive\r\n"
4842 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4843 };
4844 MockRead data_reads[] = {
4845 // Return an error, so the transaction stops here (this test isn't
4846 // interested in the rest).
4847 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4848 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4849 MockRead("Proxy-Connection: close\r\n\r\n"),
4850 };
4851
4852 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4853 data_writes, arraysize(data_writes));
4854 session_deps.socket_factory.AddSocketDataProvider(&data);
4855
4856 TestCompletionCallback callback;
4857
4858 int rv = trans->Start(&request, &callback, BoundNetLog());
4859 EXPECT_EQ(ERR_IO_PENDING, rv);
4860
4861 rv = callback.WaitForResult();
4862 EXPECT_EQ(OK, rv);
4863}
4864
[email protected]1c773ea12009-04-28 19:58:424865TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]228ff742009-06-05 01:19:594866 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404867 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434868 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424869
4870 HttpRequestInfo request;
4871 request.method = "GET";
4872 request.url = GURL("http://www.google.com/");
4873 request.load_flags = 0;
4874 request.referrer = GURL("http://the.previous.site.com/");
4875
4876 MockWrite data_writes[] = {
4877 MockWrite("GET / HTTP/1.1\r\n"
4878 "Host: www.google.com\r\n"
4879 "Connection: keep-alive\r\n"
4880 "Referer: http://the.previous.site.com/\r\n\r\n"),
4881 };
4882
4883 // Lastly, the server responds with the actual content.
4884 MockRead data_reads[] = {
4885 MockRead("HTTP/1.0 200 OK\r\n"),
4886 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4887 MockRead("Content-Length: 100\r\n\r\n"),
4888 MockRead(false, OK),
4889 };
4890
[email protected]31a2bfe2010-02-09 08:03:394891 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4892 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594893 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424894
4895 TestCompletionCallback callback;
4896
[email protected]5a1d7ca2010-04-28 20:12:274897 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424898 EXPECT_EQ(ERR_IO_PENDING, rv);
4899
4900 rv = callback.WaitForResult();
4901 EXPECT_EQ(OK, rv);
4902}
4903
4904TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594905 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404906 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434907 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424908
4909 HttpRequestInfo request;
4910 request.method = "POST";
4911 request.url = GURL("http://www.google.com/");
4912
4913 MockWrite data_writes[] = {
4914 MockWrite("POST / HTTP/1.1\r\n"
4915 "Host: www.google.com\r\n"
4916 "Connection: keep-alive\r\n"
4917 "Content-Length: 0\r\n\r\n"),
4918 };
4919
4920 // Lastly, the server responds with the actual content.
4921 MockRead data_reads[] = {
4922 MockRead("HTTP/1.0 200 OK\r\n"),
4923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4924 MockRead("Content-Length: 100\r\n\r\n"),
4925 MockRead(false, OK),
4926 };
4927
[email protected]31a2bfe2010-02-09 08:03:394928 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4929 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594930 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424931
4932 TestCompletionCallback callback;
4933
[email protected]5a1d7ca2010-04-28 20:12:274934 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424935 EXPECT_EQ(ERR_IO_PENDING, rv);
4936
4937 rv = callback.WaitForResult();
4938 EXPECT_EQ(OK, rv);
4939}
4940
4941TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594942 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404943 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434944 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424945
4946 HttpRequestInfo request;
4947 request.method = "PUT";
4948 request.url = GURL("http://www.google.com/");
4949
4950 MockWrite data_writes[] = {
4951 MockWrite("PUT / HTTP/1.1\r\n"
4952 "Host: www.google.com\r\n"
4953 "Connection: keep-alive\r\n"
4954 "Content-Length: 0\r\n\r\n"),
4955 };
4956
4957 // Lastly, the server responds with the actual content.
4958 MockRead data_reads[] = {
4959 MockRead("HTTP/1.0 200 OK\r\n"),
4960 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4961 MockRead("Content-Length: 100\r\n\r\n"),
4962 MockRead(false, OK),
4963 };
4964
[email protected]31a2bfe2010-02-09 08:03:394965 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4966 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594967 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424968
4969 TestCompletionCallback callback;
4970
[email protected]5a1d7ca2010-04-28 20:12:274971 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424972 EXPECT_EQ(ERR_IO_PENDING, rv);
4973
4974 rv = callback.WaitForResult();
4975 EXPECT_EQ(OK, rv);
4976}
4977
4978TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]228ff742009-06-05 01:19:594979 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404980 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434981 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:424982
4983 HttpRequestInfo request;
4984 request.method = "HEAD";
4985 request.url = GURL("http://www.google.com/");
4986
4987 MockWrite data_writes[] = {
4988 MockWrite("HEAD / HTTP/1.1\r\n"
4989 "Host: www.google.com\r\n"
4990 "Connection: keep-alive\r\n"
4991 "Content-Length: 0\r\n\r\n"),
4992 };
4993
4994 // Lastly, the server responds with the actual content.
4995 MockRead data_reads[] = {
4996 MockRead("HTTP/1.0 200 OK\r\n"),
4997 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4998 MockRead("Content-Length: 100\r\n\r\n"),
4999 MockRead(false, OK),
5000 };
5001
[email protected]31a2bfe2010-02-09 08:03:395002 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5003 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595004 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425005
5006 TestCompletionCallback callback;
5007
[email protected]5a1d7ca2010-04-28 20:12:275008 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425009 EXPECT_EQ(ERR_IO_PENDING, rv);
5010
5011 rv = callback.WaitForResult();
5012 EXPECT_EQ(OK, rv);
5013}
5014
5015TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]228ff742009-06-05 01:19:595016 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:405017 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435018 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:425019
5020 HttpRequestInfo request;
5021 request.method = "GET";
5022 request.url = GURL("http://www.google.com/");
5023 request.load_flags = LOAD_BYPASS_CACHE;
5024
5025 MockWrite data_writes[] = {
5026 MockWrite("GET / HTTP/1.1\r\n"
5027 "Host: www.google.com\r\n"
5028 "Connection: keep-alive\r\n"
5029 "Pragma: no-cache\r\n"
5030 "Cache-Control: no-cache\r\n\r\n"),
5031 };
5032
5033 // Lastly, the server responds with the actual content.
5034 MockRead data_reads[] = {
5035 MockRead("HTTP/1.0 200 OK\r\n"),
5036 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5037 MockRead("Content-Length: 100\r\n\r\n"),
5038 MockRead(false, OK),
5039 };
5040
[email protected]31a2bfe2010-02-09 08:03:395041 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5042 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595043 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425044
5045 TestCompletionCallback callback;
5046
[email protected]5a1d7ca2010-04-28 20:12:275047 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425048 EXPECT_EQ(ERR_IO_PENDING, rv);
5049
5050 rv = callback.WaitForResult();
5051 EXPECT_EQ(OK, rv);
5052}
5053
5054TEST_F(HttpNetworkTransactionTest,
5055 BuildRequest_CacheControlValidateCache) {
[email protected]228ff742009-06-05 01:19:595056 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:405057 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435058 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:425059
5060 HttpRequestInfo request;
5061 request.method = "GET";
5062 request.url = GURL("http://www.google.com/");
5063 request.load_flags = LOAD_VALIDATE_CACHE;
5064
5065 MockWrite data_writes[] = {
5066 MockWrite("GET / HTTP/1.1\r\n"
5067 "Host: www.google.com\r\n"
5068 "Connection: keep-alive\r\n"
5069 "Cache-Control: max-age=0\r\n\r\n"),
5070 };
5071
5072 // Lastly, the server responds with the actual content.
5073 MockRead data_reads[] = {
5074 MockRead("HTTP/1.0 200 OK\r\n"),
5075 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5076 MockRead("Content-Length: 100\r\n\r\n"),
5077 MockRead(false, OK),
5078 };
5079
[email protected]31a2bfe2010-02-09 08:03:395080 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5081 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595082 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425083
5084 TestCompletionCallback callback;
5085
[email protected]5a1d7ca2010-04-28 20:12:275086 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425087 EXPECT_EQ(ERR_IO_PENDING, rv);
5088
5089 rv = callback.WaitForResult();
5090 EXPECT_EQ(OK, rv);
5091}
5092
5093TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]228ff742009-06-05 01:19:595094 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:405095 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435096 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]1c773ea12009-04-28 19:58:425097
5098 HttpRequestInfo request;
5099 request.method = "GET";
5100 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435101 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425102
5103 MockWrite data_writes[] = {
5104 MockWrite("GET / HTTP/1.1\r\n"
5105 "Host: www.google.com\r\n"
5106 "Connection: keep-alive\r\n"
5107 "FooHeader: Bar\r\n\r\n"),
5108 };
5109
5110 // Lastly, the server responds with the actual content.
5111 MockRead data_reads[] = {
5112 MockRead("HTTP/1.0 200 OK\r\n"),
5113 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5114 MockRead("Content-Length: 100\r\n\r\n"),
5115 MockRead(false, OK),
5116 };
5117
[email protected]31a2bfe2010-02-09 08:03:395118 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5119 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595120 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425121
5122 TestCompletionCallback callback;
5123
[email protected]5a1d7ca2010-04-28 20:12:275124 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425125 EXPECT_EQ(ERR_IO_PENDING, rv);
5126
5127 rv = callback.WaitForResult();
5128 EXPECT_EQ(OK, rv);
5129}
5130
[email protected]270c6412010-03-29 22:02:475131TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
5132 SessionDependencies session_deps;
5133 scoped_ptr<HttpTransaction> trans(
5134 new HttpNetworkTransaction(CreateSession(&session_deps)));
5135
5136 HttpRequestInfo request;
5137 request.method = "GET";
5138 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435139 request.extra_headers.SetHeader("referer", "www.foo.com");
5140 request.extra_headers.SetHeader("hEllo", "Kitty");
5141 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475142
5143 MockWrite data_writes[] = {
5144 MockWrite("GET / HTTP/1.1\r\n"
5145 "Host: www.google.com\r\n"
5146 "Connection: keep-alive\r\n"
5147 "hEllo: Kitty\r\n"
5148 "FoO: bar\r\n\r\n"),
5149 };
5150
5151 // Lastly, the server responds with the actual content.
5152 MockRead data_reads[] = {
5153 MockRead("HTTP/1.0 200 OK\r\n"),
5154 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5155 MockRead("Content-Length: 100\r\n\r\n"),
5156 MockRead(false, OK),
5157 };
5158
5159 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5160 data_writes, arraysize(data_writes));
5161 session_deps.socket_factory.AddSocketDataProvider(&data);
5162
5163 TestCompletionCallback callback;
5164
[email protected]5a1d7ca2010-04-28 20:12:275165 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475166 EXPECT_EQ(ERR_IO_PENDING, rv);
5167
5168 rv = callback.WaitForResult();
5169 EXPECT_EQ(OK, rv);
5170}
5171
[email protected]3cd17242009-06-23 02:59:025172TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:095173 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005174 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025175
5176 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435177 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025178
5179 HttpRequestInfo request;
5180 request.method = "GET";
5181 request.url = GURL("http://www.google.com/");
5182 request.load_flags = 0;
5183
5184 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5185 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5186
5187 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355188 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025189 MockWrite("GET / HTTP/1.1\r\n"
5190 "Host: www.google.com\r\n"
5191 "Connection: keep-alive\r\n\r\n")
5192 };
5193
5194 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595195 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025196 MockRead("HTTP/1.0 200 OK\r\n"),
5197 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5198 MockRead("Payload"),
5199 MockRead(false, OK)
5200 };
5201
[email protected]31a2bfe2010-02-09 08:03:395202 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5203 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595204 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025205
5206 TestCompletionCallback callback;
5207
[email protected]5a1d7ca2010-04-28 20:12:275208 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025209 EXPECT_EQ(ERR_IO_PENDING, rv);
5210
5211 rv = callback.WaitForResult();
5212 EXPECT_EQ(OK, rv);
5213
5214 const HttpResponseInfo* response = trans->GetResponseInfo();
5215 EXPECT_FALSE(response == NULL);
5216
5217 std::string response_text;
5218 rv = ReadTransaction(trans.get(), &response_text);
5219 EXPECT_EQ(OK, rv);
5220 EXPECT_EQ("Payload", response_text);
5221}
5222
5223TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:095224 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005225 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025226
5227 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435228 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025229
5230 HttpRequestInfo request;
5231 request.method = "GET";
5232 request.url = GURL("https://www.google.com/");
5233 request.load_flags = 0;
5234
5235 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5236 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5237
5238 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355239 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5240 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025241 MockWrite("GET / HTTP/1.1\r\n"
5242 "Host: www.google.com\r\n"
5243 "Connection: keep-alive\r\n\r\n")
5244 };
5245
5246 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355247 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5248 arraysize(read_buffer)),
5249 MockRead("HTTP/1.0 200 OK\r\n"),
5250 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5251 MockRead("Payload"),
5252 MockRead(false, OK)
5253 };
5254
[email protected]31a2bfe2010-02-09 08:03:395255 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5256 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595257 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355258
[email protected]5ecc992a42009-11-11 01:41:595259 SSLSocketDataProvider ssl(true, OK);
5260 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355261
5262 TestCompletionCallback callback;
5263
[email protected]5a1d7ca2010-04-28 20:12:275264 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355265 EXPECT_EQ(ERR_IO_PENDING, rv);
5266
5267 rv = callback.WaitForResult();
5268 EXPECT_EQ(OK, rv);
5269
5270 const HttpResponseInfo* response = trans->GetResponseInfo();
5271 EXPECT_FALSE(response == NULL);
5272
5273 std::string response_text;
5274 rv = ReadTransaction(trans.get(), &response_text);
5275 EXPECT_EQ(OK, rv);
5276 EXPECT_EQ("Payload", response_text);
5277}
5278
5279TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]80d6524d2009-08-18 03:58:095280 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005281 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355282
5283 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435284 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355285
5286 HttpRequestInfo request;
5287 request.method = "GET";
5288 request.url = GURL("http://www.google.com/");
5289 request.load_flags = 0;
5290
5291 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5292 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375293 const char kSOCKS5OkRequest[] = {
5294 0x05, // Version
5295 0x01, // Command (CONNECT)
5296 0x00, // Reserved.
5297 0x03, // Address type (DOMAINNAME).
5298 0x0E, // Length of domain (14)
5299 // Domain string:
5300 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5301 0x00, 0x50, // 16-bit port (80)
5302 };
[email protected]e0c27be2009-07-15 13:09:355303 const char kSOCKS5OkResponse[] =
5304 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5305
5306 MockWrite data_writes[] = {
5307 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5308 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5309 MockWrite("GET / HTTP/1.1\r\n"
5310 "Host: www.google.com\r\n"
5311 "Connection: keep-alive\r\n\r\n")
5312 };
5313
5314 MockRead data_reads[] = {
5315 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5316 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5317 MockRead("HTTP/1.0 200 OK\r\n"),
5318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5319 MockRead("Payload"),
5320 MockRead(false, OK)
5321 };
5322
[email protected]31a2bfe2010-02-09 08:03:395323 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5324 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595325 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355326
5327 TestCompletionCallback callback;
5328
[email protected]5a1d7ca2010-04-28 20:12:275329 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355330 EXPECT_EQ(ERR_IO_PENDING, rv);
5331
5332 rv = callback.WaitForResult();
5333 EXPECT_EQ(OK, rv);
5334
5335 const HttpResponseInfo* response = trans->GetResponseInfo();
5336 EXPECT_FALSE(response == NULL);
5337
5338 std::string response_text;
5339 rv = ReadTransaction(trans.get(), &response_text);
5340 EXPECT_EQ(OK, rv);
5341 EXPECT_EQ("Payload", response_text);
5342}
5343
5344TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]80d6524d2009-08-18 03:58:095345 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005346 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355347
5348 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435349 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355350
5351 HttpRequestInfo request;
5352 request.method = "GET";
5353 request.url = GURL("https://www.google.com/");
5354 request.load_flags = 0;
5355
5356 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5357 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375358 const unsigned char kSOCKS5OkRequest[] = {
5359 0x05, // Version
5360 0x01, // Command (CONNECT)
5361 0x00, // Reserved.
5362 0x03, // Address type (DOMAINNAME).
5363 0x0E, // Length of domain (14)
5364 // Domain string:
5365 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5366 0x01, 0xBB, // 16-bit port (443)
5367 };
5368
[email protected]e0c27be2009-07-15 13:09:355369 const char kSOCKS5OkResponse[] =
5370 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5371
5372 MockWrite data_writes[] = {
5373 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5374 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5375 arraysize(kSOCKS5OkRequest)),
5376 MockWrite("GET / HTTP/1.1\r\n"
5377 "Host: www.google.com\r\n"
5378 "Connection: keep-alive\r\n\r\n")
5379 };
5380
5381 MockRead data_reads[] = {
5382 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5383 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025384 MockRead("HTTP/1.0 200 OK\r\n"),
5385 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5386 MockRead("Payload"),
5387 MockRead(false, OK)
5388 };
5389
[email protected]31a2bfe2010-02-09 08:03:395390 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5391 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595392 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025393
[email protected]5ecc992a42009-11-11 01:41:595394 SSLSocketDataProvider ssl(true, OK);
5395 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025396
5397 TestCompletionCallback callback;
5398
[email protected]5a1d7ca2010-04-28 20:12:275399 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025400 EXPECT_EQ(ERR_IO_PENDING, rv);
5401
5402 rv = callback.WaitForResult();
5403 EXPECT_EQ(OK, rv);
5404
5405 const HttpResponseInfo* response = trans->GetResponseInfo();
5406 EXPECT_FALSE(response == NULL);
5407
5408 std::string response_text;
5409 rv = ReadTransaction(trans.get(), &response_text);
5410 EXPECT_EQ(OK, rv);
5411 EXPECT_EQ("Payload", response_text);
5412}
5413
[email protected]04e5be32009-06-26 20:00:315414// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065415
5416struct GroupNameTest {
5417 std::string proxy_server;
5418 std::string url;
5419 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185420 bool ssl;
[email protected]2d731a32010-04-29 01:04:065421};
5422
5423scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
5424 const std::string& proxy_server) {
[email protected]81cdfcd2010-10-16 00:49:005425 SessionDependencies session_deps(ProxyService::CreateFixed(proxy_server));
[email protected]2d731a32010-04-29 01:04:065426 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
5427
5428 HttpAlternateProtocols* alternate_protocols =
5429 session->mutable_alternate_protocols();
5430 alternate_protocols->SetAlternateProtocolFor(
5431 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355432 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065433
5434 return session;
5435}
5436
5437int GroupNameTransactionHelper(
5438 const std::string& url,
5439 const scoped_refptr<HttpNetworkSession>& session) {
5440 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5441
5442 HttpRequestInfo request;
5443 request.method = "GET";
5444 request.url = GURL(url);
5445 request.load_flags = 0;
5446
5447 TestCompletionCallback callback;
5448
5449 // We do not complete this request, the dtor will clean the transaction up.
5450 return trans->Start(&request, &callback, BoundNetLog());
5451}
5452
5453TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5454 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315455 {
[email protected]2d731a32010-04-29 01:04:065456 "", // unused
[email protected]04e5be32009-06-26 20:00:315457 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545458 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185459 false,
[email protected]2ff8b312010-04-26 22:20:545460 },
5461 {
[email protected]2d731a32010-04-29 01:04:065462 "", // unused
[email protected]2ff8b312010-04-26 22:20:545463 "http://[2001:1418:13:1::25]/direct",
5464 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185465 false,
[email protected]04e5be32009-06-26 20:00:315466 },
[email protected]04e5be32009-06-26 20:00:315467
5468 // SSL Tests
5469 {
[email protected]2d731a32010-04-29 01:04:065470 "", // unused
[email protected]04e5be32009-06-26 20:00:315471 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025472 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185473 true,
[email protected]04e5be32009-06-26 20:00:315474 },
5475 {
[email protected]2d731a32010-04-29 01:04:065476 "", // unused
5477 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025478 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185479 true,
[email protected]04e5be32009-06-26 20:00:315480 },
5481 {
[email protected]2d731a32010-04-29 01:04:065482 "", // unused
[email protected]2ff8b312010-04-26 22:20:545483 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025484 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185485 true,
[email protected]2ff8b312010-04-26 22:20:545486 },
[email protected]2d731a32010-04-29 01:04:065487 };
[email protected]2ff8b312010-04-26 22:20:545488
[email protected]8e6441ca2010-08-19 05:56:385489 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065490
5491 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5492 scoped_refptr<HttpNetworkSession> session(
5493 SetupSessionForGroupNameTests(tests[i].proxy_server));
5494
5495 HttpNetworkSessionPeer peer(session);
[email protected]2431756e2010-09-29 20:26:135496 CaptureGroupNameTCPSocketPool* tcp_conn_pool =
5497 new CaptureGroupNameTCPSocketPool(session);
[email protected]2d731a32010-04-29 01:04:065498 peer.SetTCPSocketPool(tcp_conn_pool);
[email protected]2431756e2010-09-29 20:26:135499 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5500 new CaptureGroupNameSSLSocketPool(session.get());
[email protected]e60e47a2010-07-14 03:37:185501 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065502
5503 EXPECT_EQ(ERR_IO_PENDING,
5504 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185505 if (tests[i].ssl)
5506 EXPECT_EQ(tests[i].expected_group_name,
5507 ssl_conn_pool->last_group_name_received());
5508 else
5509 EXPECT_EQ(tests[i].expected_group_name,
5510 tcp_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065511 }
5512
[email protected]8e6441ca2010-08-19 05:56:385513 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065514}
5515
5516TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5517 const GroupNameTest tests[] = {
5518 {
5519 "http_proxy",
5520 "http://www.google.com/http_proxy_normal",
5521 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185522 false,
[email protected]2d731a32010-04-29 01:04:065523 },
5524
5525 // SSL Tests
5526 {
5527 "http_proxy",
5528 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025529 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185530 true,
[email protected]2d731a32010-04-29 01:04:065531 },
[email protected]af3490e2010-10-16 21:02:295532
[email protected]9faeded92010-04-29 20:03:055533 {
5534 "http_proxy",
5535 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025536 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185537 true,
[email protected]9faeded92010-04-29 20:03:055538 },
[email protected]2d731a32010-04-29 01:04:065539 };
5540
[email protected]8e6441ca2010-08-19 05:56:385541 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065542
5543 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
5544 scoped_refptr<HttpNetworkSession> session(
5545 SetupSessionForGroupNameTests(tests[i].proxy_server));
5546
5547 HttpNetworkSessionPeer peer(session);
5548
[email protected]e60e47a2010-07-14 03:37:185549 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135550 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
5551 new CaptureGroupNameHttpProxySocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185552 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135553 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5554 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185555 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065556
5557 EXPECT_EQ(ERR_IO_PENDING,
5558 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185559 if (tests[i].ssl)
5560 EXPECT_EQ(tests[i].expected_group_name,
5561 ssl_conn_pool->last_group_name_received());
5562 else
5563 EXPECT_EQ(tests[i].expected_group_name,
5564 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065565 }
5566
[email protected]8e6441ca2010-08-19 05:56:385567 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065568}
5569
5570TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5571 const GroupNameTest tests[] = {
5572 {
5573 "socks4://socks_proxy:1080",
5574 "http://www.google.com/socks4_direct",
5575 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185576 false,
[email protected]2d731a32010-04-29 01:04:065577 },
5578 {
5579 "socks5://socks_proxy:1080",
5580 "http://www.google.com/socks5_direct",
5581 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185582 false,
[email protected]2d731a32010-04-29 01:04:065583 },
5584
5585 // SSL Tests
5586 {
5587 "socks4://socks_proxy:1080",
5588 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025589 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185590 true,
[email protected]2d731a32010-04-29 01:04:065591 },
5592 {
5593 "socks5://socks_proxy:1080",
5594 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025595 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185596 true,
[email protected]2d731a32010-04-29 01:04:065597 },
[email protected]af3490e2010-10-16 21:02:295598
[email protected]9faeded92010-04-29 20:03:055599 {
5600 "socks4://socks_proxy:1080",
5601 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025602 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185603 true,
[email protected]9faeded92010-04-29 20:03:055604 },
[email protected]04e5be32009-06-26 20:00:315605 };
5606
[email protected]8e6441ca2010-08-19 05:56:385607 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545608
[email protected]04e5be32009-06-26 20:00:315609 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]2d731a32010-04-29 01:04:065610 scoped_refptr<HttpNetworkSession> session(
5611 SetupSessionForGroupNameTests(tests[i].proxy_server));
5612 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315613
[email protected]e60e47a2010-07-14 03:37:185614 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135615 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
5616 new CaptureGroupNameSOCKSSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185617 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135618 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
5619 new CaptureGroupNameSSLSocketPool(session);
[email protected]e60e47a2010-07-14 03:37:185620 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315621
[email protected]5695b8c2009-09-30 21:36:435622 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315623
[email protected]2d731a32010-04-29 01:04:065624 EXPECT_EQ(ERR_IO_PENDING,
5625 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185626 if (tests[i].ssl)
5627 EXPECT_EQ(tests[i].expected_group_name,
5628 ssl_conn_pool->last_group_name_received());
5629 else
5630 EXPECT_EQ(tests[i].expected_group_name,
5631 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315632 }
[email protected]2ff8b312010-04-26 22:20:545633
[email protected]8e6441ca2010-08-19 05:56:385634 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315635}
5636
[email protected]9172a982009-06-06 00:30:255637TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]5c6a17e2009-06-10 00:54:545638 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005639 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325640
[email protected]69719062010-01-05 20:09:215641 // This simulates failure resolving all hostnames; that means we will fail
5642 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325643 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5644
[email protected]9172a982009-06-06 00:30:255645 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435646 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255647
5648 HttpRequestInfo request;
5649 request.method = "GET";
5650 request.url = GURL("http://www.google.com/");
5651
5652 TestCompletionCallback callback;
5653
[email protected]5a1d7ca2010-04-28 20:12:275654 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255655 EXPECT_EQ(ERR_IO_PENDING, rv);
5656
[email protected]9172a982009-06-06 00:30:255657 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015658 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255659}
5660
[email protected]f3e6c1e2009-06-15 20:52:125661// Host resolution observer used by
5662// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5663// resovle requests are issued with a referrer of |expected_referrer|.
5664class ResolutionReferrerObserver : public HostResolver::Observer {
5665 public:
5666 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5667 : expected_referrer_(expected_referrer),
5668 called_start_with_referrer_(false),
5669 called_finish_with_referrer_(false) {
5670 }
5671
5672 virtual void OnStartResolution(int id,
5673 const HostResolver::RequestInfo& info) {
5674 if (info.referrer() == expected_referrer_)
5675 called_start_with_referrer_ = true;
5676 }
5677
5678 virtual void OnFinishResolutionWithStatus(
5679 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5680 if (info.referrer() == expected_referrer_)
5681 called_finish_with_referrer_ = true;
5682 }
5683
[email protected]eb255d32009-06-17 02:11:035684 virtual void OnCancelResolution(int id,
5685 const HostResolver::RequestInfo& info ) {
5686 FAIL() << "Should not be cancelling any requests!";
5687 }
5688
[email protected]f3e6c1e2009-06-15 20:52:125689 bool did_complete_with_expected_referrer() const {
5690 return called_start_with_referrer_ && called_finish_with_referrer_;
5691 }
5692
5693 private:
5694 GURL expected_referrer_;
5695 bool called_start_with_referrer_;
5696 bool called_finish_with_referrer_;
5697
5698 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5699};
5700
5701// Make sure that when HostResolver::Resolve() is invoked, it passes through
5702// the "referrer". This is depended on by the DNS prefetch observer.
5703TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5704 GURL referrer = GURL("http://expected-referrer/");
5705 EXPECT_TRUE(referrer.is_valid());
5706 ResolutionReferrerObserver resolution_observer(referrer);
5707
5708 SessionDependencies session_deps;
5709 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435710 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125711
5712 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145713 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125714
5715 // Connect up a mock socket which will fail when reading.
5716 MockRead data_reads[] = {
5717 MockRead(false, ERR_FAILED),
5718 };
[email protected]31a2bfe2010-02-09 08:03:395719 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595720 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125721
5722 // Issue a request, containing an HTTP referrer.
5723 HttpRequestInfo request;
5724 request.method = "GET";
5725 request.referrer = referrer;
5726 request.url = GURL("http://www.google.com/");
5727
5728 // Run the request until it fails reading from the socket.
5729 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275730 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125731 EXPECT_EQ(ERR_IO_PENDING, rv);
5732 rv = callback.WaitForResult();
5733 EXPECT_EQ(ERR_FAILED, rv);
5734
5735 // Check that the host resolution observer saw |referrer|.
5736 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5737}
5738
[email protected]685af592010-05-11 19:31:245739// Base test to make sure that when the load flags for a request specify to
5740// bypass the cache, the DNS cache is not used.
5741void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]3b9cca42009-06-16 01:08:285742 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325743
[email protected]a2c2fb92009-07-18 07:31:045744 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545745 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325746
[email protected]3b9cca42009-06-16 01:08:285747 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435748 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285749
5750 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5751 // a synchronous lookup.)
5752 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145753 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105754 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275755 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285756 EXPECT_EQ(OK, rv);
5757
5758 // Verify that it was added to host cache, by doing a subsequent async lookup
5759 // and confirming it completes synchronously.
5760 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465761 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105762 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275763 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325764 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285765
5766 // Inject a failure the next time that "www.google.com" is resolved. This way
5767 // we can tell if the next lookup hit the cache, or the "network".
5768 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325769 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285770
5771 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5772 // first read -- this won't be reached as the host resolution will fail first.
5773 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395774 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595775 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285776
5777 // Issue a request, asking to bypass the cache(s).
5778 HttpRequestInfo request;
5779 request.method = "GET";
[email protected]685af592010-05-11 19:31:245780 request.load_flags = load_flags;
[email protected]3b9cca42009-06-16 01:08:285781 request.url = GURL("http://www.google.com/");
5782
5783 // Run the request.
5784 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275785 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285786 ASSERT_EQ(ERR_IO_PENDING, rv);
5787 rv = callback.WaitForResult();
5788
5789 // If we bypassed the cache, we would have gotten a failure while resolving
5790 // "www.google.com".
5791 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5792}
5793
[email protected]685af592010-05-11 19:31:245794// There are multiple load flags that should trigger the host cache bypass.
5795// Test each in isolation:
5796TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5797 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5798}
5799
5800TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5801 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5802}
5803
5804TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5805 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5806}
5807
[email protected]0877e3d2009-10-17 22:29:575808// Make sure we can handle an error when writing the request.
5809TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5810 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275811 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575812
5813 HttpRequestInfo request;
5814 request.method = "GET";
5815 request.url = GURL("http://www.foo.com/");
5816 request.load_flags = 0;
5817
5818 MockWrite write_failure[] = {
5819 MockWrite(true, ERR_CONNECTION_RESET),
5820 };
[email protected]31a2bfe2010-02-09 08:03:395821 StaticSocketDataProvider data(NULL, 0,
5822 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595823 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575824
5825 TestCompletionCallback callback;
5826
5827 scoped_ptr<HttpTransaction> trans(
5828 new HttpNetworkTransaction(CreateSession(&session_deps)));
5829
[email protected]5a1d7ca2010-04-28 20:12:275830 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575831 EXPECT_EQ(ERR_IO_PENDING, rv);
5832
5833 rv = callback.WaitForResult();
5834 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5835}
5836
5837// Check that a connection closed after the start of the headers finishes ok.
5838TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5839 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275840 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575841
5842 HttpRequestInfo request;
5843 request.method = "GET";
5844 request.url = GURL("http://www.foo.com/");
5845 request.load_flags = 0;
5846
5847 MockRead data_reads[] = {
5848 MockRead("HTTP/1."),
5849 MockRead(false, OK),
5850 };
5851
[email protected]31a2bfe2010-02-09 08:03:395852 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595853 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575854
5855 TestCompletionCallback callback;
5856
5857 scoped_ptr<HttpTransaction> trans(
5858 new HttpNetworkTransaction(CreateSession(&session_deps)));
5859
[email protected]5a1d7ca2010-04-28 20:12:275860 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575861 EXPECT_EQ(ERR_IO_PENDING, rv);
5862
5863 rv = callback.WaitForResult();
5864 EXPECT_EQ(OK, rv);
5865
5866 const HttpResponseInfo* response = trans->GetResponseInfo();
5867 EXPECT_TRUE(response != NULL);
5868
5869 EXPECT_TRUE(response->headers != NULL);
5870 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5871
5872 std::string response_data;
5873 rv = ReadTransaction(trans.get(), &response_data);
5874 EXPECT_EQ(OK, rv);
5875 EXPECT_EQ("", response_data);
5876}
5877
5878// Make sure that a dropped connection while draining the body for auth
5879// restart does the right thing.
5880TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5881 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275882 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575883
5884 HttpRequestInfo request;
5885 request.method = "GET";
5886 request.url = GURL("http://www.google.com/");
5887 request.load_flags = 0;
5888
5889 MockWrite data_writes1[] = {
5890 MockWrite("GET / HTTP/1.1\r\n"
5891 "Host: www.google.com\r\n"
5892 "Connection: keep-alive\r\n\r\n"),
5893 };
5894
5895 MockRead data_reads1[] = {
5896 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5897 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5898 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5899 MockRead("Content-Length: 14\r\n\r\n"),
5900 MockRead("Unauth"),
5901 MockRead(true, ERR_CONNECTION_RESET),
5902 };
5903
[email protected]31a2bfe2010-02-09 08:03:395904 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5905 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595906 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575907
5908 // After calling trans->RestartWithAuth(), this is the request we should
5909 // be issuing -- the final header line contains the credentials.
5910 MockWrite data_writes2[] = {
5911 MockWrite("GET / HTTP/1.1\r\n"
5912 "Host: www.google.com\r\n"
5913 "Connection: keep-alive\r\n"
5914 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5915 };
5916
5917 // Lastly, the server responds with the actual content.
5918 MockRead data_reads2[] = {
5919 MockRead("HTTP/1.1 200 OK\r\n"),
5920 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5921 MockRead("Content-Length: 100\r\n\r\n"),
5922 MockRead(false, OK),
5923 };
5924
[email protected]31a2bfe2010-02-09 08:03:395925 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5926 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595927 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575928
5929 TestCompletionCallback callback1;
5930
[email protected]0b0bf032010-09-21 18:08:505931 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5932
[email protected]5a1d7ca2010-04-28 20:12:275933 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575934 EXPECT_EQ(ERR_IO_PENDING, rv);
5935
5936 rv = callback1.WaitForResult();
5937 EXPECT_EQ(OK, rv);
5938
5939 const HttpResponseInfo* response = trans->GetResponseInfo();
5940 EXPECT_FALSE(response == NULL);
5941
5942 // The password prompt info should have been set in response->auth_challenge.
5943 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5944
5945 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5946 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5947 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5948
5949 TestCompletionCallback callback2;
5950
[email protected]13c8a092010-07-29 06:15:445951 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:575952 EXPECT_EQ(ERR_IO_PENDING, rv);
5953
5954 rv = callback2.WaitForResult();
5955 EXPECT_EQ(OK, rv);
5956
5957 response = trans->GetResponseInfo();
5958 EXPECT_FALSE(response == NULL);
5959 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5960 EXPECT_EQ(100, response->headers->GetContentLength());
5961}
5962
5963// Test HTTPS connections going through a proxy that sends extra data.
5964TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005965 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575966
5967 HttpRequestInfo request;
5968 request.method = "GET";
5969 request.url = GURL("https://www.google.com/");
5970 request.load_flags = 0;
5971
5972 MockRead proxy_reads[] = {
5973 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5974 MockRead(false, OK)
5975 };
5976
[email protected]31a2bfe2010-02-09 08:03:395977 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595978 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575979
[email protected]5ecc992a42009-11-11 01:41:595980 session_deps.socket_factory.AddSocketDataProvider(&data);
5981 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575982
5983 TestCompletionCallback callback;
5984
5985 session_deps.socket_factory.ResetNextMockIndexes();
5986
5987 scoped_ptr<HttpTransaction> trans(
5988 new HttpNetworkTransaction(CreateSession(&session_deps)));
5989
[email protected]5a1d7ca2010-04-28 20:12:275990 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575991 EXPECT_EQ(ERR_IO_PENDING, rv);
5992
5993 rv = callback.WaitForResult();
5994 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5995}
5996
[email protected]e22e1362009-11-23 21:31:125997TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465998 SessionDependencies session_deps;
5999 scoped_ptr<HttpTransaction> trans(
6000 new HttpNetworkTransaction(CreateSession(&session_deps)));
6001
6002 HttpRequestInfo request;
6003 request.method = "GET";
6004 request.url = GURL("http://www.google.com/");
6005 request.load_flags = 0;
6006
[email protected]e22e1362009-11-23 21:31:126007 MockRead data_reads[] = {
6008 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6009 MockRead(false, OK),
6010 };
[email protected]9492e4a2010-02-24 00:58:466011
6012 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6013 session_deps.socket_factory.AddSocketDataProvider(&data);
6014
6015 TestCompletionCallback callback;
6016
[email protected]5a1d7ca2010-04-28 20:12:276017 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466018 EXPECT_EQ(ERR_IO_PENDING, rv);
6019
6020 EXPECT_EQ(OK, callback.WaitForResult());
6021
6022 const HttpResponseInfo* response = trans->GetResponseInfo();
6023 EXPECT_TRUE(response != NULL);
6024
6025 EXPECT_TRUE(response->headers != NULL);
6026 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6027
6028 std::string response_data;
6029 rv = ReadTransaction(trans.get(), &response_data);
6030 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126031}
6032
[email protected]95d88ffe2010-02-04 21:25:336033TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
6034 SessionDependencies session_deps;
6035 scoped_ptr<HttpTransaction> trans(
6036 new HttpNetworkTransaction(CreateSession(&session_deps)));
6037
6038 HttpRequestInfo request;
6039 request.method = "POST";
6040 request.url = GURL("http://www.google.com/upload");
6041 request.upload_data = new UploadData;
6042 request.load_flags = 0;
6043
6044 FilePath temp_file_path;
6045 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6046 const uint64 kFakeSize = 100000; // file is actually blank
6047
6048 std::vector<UploadData::Element> elements;
6049 UploadData::Element element;
6050 element.SetToFilePath(temp_file_path);
6051 element.SetContentLength(kFakeSize);
6052 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536053 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336054 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6055
6056 MockRead data_reads[] = {
6057 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6058 MockRead("hello world"),
6059 MockRead(false, OK),
6060 };
[email protected]31a2bfe2010-02-09 08:03:396061 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336062 session_deps.socket_factory.AddSocketDataProvider(&data);
6063
6064 TestCompletionCallback callback;
6065
[email protected]5a1d7ca2010-04-28 20:12:276066 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336067 EXPECT_EQ(ERR_IO_PENDING, rv);
6068
6069 rv = callback.WaitForResult();
6070 EXPECT_EQ(OK, rv);
6071
6072 const HttpResponseInfo* response = trans->GetResponseInfo();
6073 EXPECT_TRUE(response != NULL);
6074
6075 EXPECT_TRUE(response->headers != NULL);
6076 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6077
6078 std::string response_data;
6079 rv = ReadTransaction(trans.get(), &response_data);
6080 EXPECT_EQ(OK, rv);
6081 EXPECT_EQ("hello world", response_data);
6082
6083 file_util::Delete(temp_file_path, false);
6084}
6085
[email protected]6624b4622010-03-29 19:58:366086TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
6087 // If we try to upload an unreadable file, the network stack should report
6088 // the file size as zero and upload zero bytes for that file.
6089 SessionDependencies session_deps;
6090 scoped_ptr<HttpTransaction> trans(
6091 new HttpNetworkTransaction(CreateSession(&session_deps)));
6092
6093 FilePath temp_file;
6094 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6095 std::string temp_file_content("Unreadable file.");
6096 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6097 temp_file_content.length()));
6098 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6099
6100 HttpRequestInfo request;
6101 request.method = "POST";
6102 request.url = GURL("http://www.google.com/upload");
6103 request.upload_data = new UploadData;
6104 request.load_flags = 0;
6105
6106 std::vector<UploadData::Element> elements;
6107 UploadData::Element element;
6108 element.SetToFilePath(temp_file);
6109 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536110 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366111
6112 MockRead data_reads[] = {
6113 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6114 MockRead(false, OK),
6115 };
6116 MockWrite data_writes[] = {
6117 MockWrite("POST /upload HTTP/1.1\r\n"
6118 "Host: www.google.com\r\n"
6119 "Connection: keep-alive\r\n"
6120 "Content-Length: 0\r\n\r\n"),
6121 MockWrite(false, OK),
6122 };
6123 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6124 arraysize(data_writes));
6125 session_deps.socket_factory.AddSocketDataProvider(&data);
6126
6127 TestCompletionCallback callback;
6128
[email protected]5a1d7ca2010-04-28 20:12:276129 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366130 EXPECT_EQ(ERR_IO_PENDING, rv);
6131
6132 rv = callback.WaitForResult();
6133 EXPECT_EQ(OK, rv);
6134
6135 const HttpResponseInfo* response = trans->GetResponseInfo();
6136 EXPECT_TRUE(response != NULL);
6137 EXPECT_TRUE(response->headers != NULL);
6138 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6139
6140 file_util::Delete(temp_file, false);
6141}
6142
6143TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
6144 SessionDependencies session_deps;
6145 scoped_ptr<HttpTransaction> trans(
6146 new HttpNetworkTransaction(CreateSession(&session_deps)));
6147
6148 FilePath temp_file;
6149 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6150 std::string temp_file_contents("Unreadable file.");
6151 std::string unreadable_contents(temp_file_contents.length(), '\0');
6152 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6153 temp_file_contents.length()));
6154
6155 HttpRequestInfo request;
6156 request.method = "POST";
6157 request.url = GURL("http://www.google.com/upload");
6158 request.upload_data = new UploadData;
6159 request.load_flags = 0;
6160
6161 std::vector<UploadData::Element> elements;
6162 UploadData::Element element;
6163 element.SetToFilePath(temp_file);
6164 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536165 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366166
6167 MockRead data_reads[] = {
6168 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6169 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6170 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6171
6172 MockRead("HTTP/1.1 200 OK\r\n"),
6173 MockRead("Content-Length: 0\r\n\r\n"),
6174 MockRead(false, OK),
6175 };
6176 MockWrite data_writes[] = {
6177 MockWrite("POST /upload HTTP/1.1\r\n"
6178 "Host: www.google.com\r\n"
6179 "Connection: keep-alive\r\n"
6180 "Content-Length: 16\r\n\r\n"),
6181 MockWrite(false, temp_file_contents.c_str()),
6182
6183 MockWrite("POST /upload HTTP/1.1\r\n"
6184 "Host: www.google.com\r\n"
6185 "Connection: keep-alive\r\n"
6186 "Content-Length: 16\r\n"
6187 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6188 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6189 MockWrite(false, OK),
6190 };
6191 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6192 arraysize(data_writes));
6193 session_deps.socket_factory.AddSocketDataProvider(&data);
6194
6195 TestCompletionCallback callback1;
6196
[email protected]5a1d7ca2010-04-28 20:12:276197 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366198 EXPECT_EQ(ERR_IO_PENDING, rv);
6199
6200 rv = callback1.WaitForResult();
6201 EXPECT_EQ(OK, rv);
6202
6203 const HttpResponseInfo* response = trans->GetResponseInfo();
6204 EXPECT_TRUE(response != NULL);
6205 EXPECT_TRUE(response->headers != NULL);
6206 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6207
6208 // The password prompt info should have been set in response->auth_challenge.
6209 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6210 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6211 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6212 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6213
6214 // Now make the file unreadable and try again.
6215 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6216
6217 TestCompletionCallback callback2;
6218
[email protected]13c8a092010-07-29 06:15:446219 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366220 EXPECT_EQ(ERR_IO_PENDING, rv);
6221
6222 rv = callback2.WaitForResult();
6223 EXPECT_EQ(OK, rv);
6224
6225 response = trans->GetResponseInfo();
6226 EXPECT_TRUE(response != NULL);
6227 EXPECT_TRUE(response->headers != NULL);
6228 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6229 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6230
6231 file_util::Delete(temp_file, false);
6232}
6233
[email protected]aeefc9e82010-02-19 16:18:276234// Tests that changes to Auth realms are treated like auth rejections.
6235TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6236 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276237
6238 HttpRequestInfo request;
6239 request.method = "GET";
6240 request.url = GURL("http://www.google.com/");
6241 request.load_flags = 0;
6242
6243 // First transaction will request a resource and receive a Basic challenge
6244 // with realm="first_realm".
6245 MockWrite data_writes1[] = {
6246 MockWrite("GET / HTTP/1.1\r\n"
6247 "Host: www.google.com\r\n"
6248 "Connection: keep-alive\r\n"
6249 "\r\n"),
6250 };
6251 MockRead data_reads1[] = {
6252 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6253 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6254 "\r\n"),
6255 };
6256
6257 // After calling trans->RestartWithAuth(), provide an Authentication header
6258 // for first_realm. The server will reject and provide a challenge with
6259 // second_realm.
6260 MockWrite data_writes2[] = {
6261 MockWrite("GET / HTTP/1.1\r\n"
6262 "Host: www.google.com\r\n"
6263 "Connection: keep-alive\r\n"
6264 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6265 "\r\n"),
6266 };
6267 MockRead data_reads2[] = {
6268 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6269 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6270 "\r\n"),
6271 };
6272
6273 // This again fails, and goes back to first_realm. Make sure that the
6274 // entry is removed from cache.
6275 MockWrite data_writes3[] = {
6276 MockWrite("GET / HTTP/1.1\r\n"
6277 "Host: www.google.com\r\n"
6278 "Connection: keep-alive\r\n"
6279 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6280 "\r\n"),
6281 };
6282 MockRead data_reads3[] = {
6283 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6284 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6285 "\r\n"),
6286 };
6287
6288 // Try one last time (with the correct password) and get the resource.
6289 MockWrite data_writes4[] = {
6290 MockWrite("GET / HTTP/1.1\r\n"
6291 "Host: www.google.com\r\n"
6292 "Connection: keep-alive\r\n"
6293 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6294 "\r\n"),
6295 };
6296 MockRead data_reads4[] = {
6297 MockRead("HTTP/1.1 200 OK\r\n"
6298 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506299 "Content-Length: 5\r\n"
6300 "\r\n"
6301 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276302 };
6303
6304 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6305 data_writes1, arraysize(data_writes1));
6306 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6307 data_writes2, arraysize(data_writes2));
6308 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6309 data_writes3, arraysize(data_writes3));
6310 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6311 data_writes4, arraysize(data_writes4));
6312 session_deps.socket_factory.AddSocketDataProvider(&data1);
6313 session_deps.socket_factory.AddSocketDataProvider(&data2);
6314 session_deps.socket_factory.AddSocketDataProvider(&data3);
6315 session_deps.socket_factory.AddSocketDataProvider(&data4);
6316
6317 TestCompletionCallback callback1;
6318
[email protected]0b0bf032010-09-21 18:08:506319 scoped_ptr<HttpTransaction> trans(
6320 new HttpNetworkTransaction(CreateSession(&session_deps)));
6321
[email protected]aeefc9e82010-02-19 16:18:276322 // Issue the first request with Authorize headers. There should be a
6323 // password prompt for first_realm waiting to be filled in after the
6324 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276325 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276326 EXPECT_EQ(ERR_IO_PENDING, rv);
6327 rv = callback1.WaitForResult();
6328 EXPECT_EQ(OK, rv);
6329 const HttpResponseInfo* response = trans->GetResponseInfo();
6330 ASSERT_FALSE(response == NULL);
6331 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6332 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6333 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6334 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6335
6336 // Issue the second request with an incorrect password. There should be a
6337 // password prompt for second_realm waiting to be filled in after the
6338 // transaction completes.
6339 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446340 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276341 EXPECT_EQ(ERR_IO_PENDING, rv);
6342 rv = callback2.WaitForResult();
6343 EXPECT_EQ(OK, rv);
6344 response = trans->GetResponseInfo();
6345 ASSERT_FALSE(response == NULL);
6346 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6347 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6348 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6349 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6350
6351 // Issue the third request with another incorrect password. There should be
6352 // a password prompt for first_realm waiting to be filled in. If the password
6353 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6354 // first_realm was not correctly removed.
6355 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446356 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276357 EXPECT_EQ(ERR_IO_PENDING, rv);
6358 rv = callback3.WaitForResult();
6359 EXPECT_EQ(OK, rv);
6360 response = trans->GetResponseInfo();
6361 ASSERT_FALSE(response == NULL);
6362 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6363 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6364 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6365 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6366
6367 // Issue the fourth request with the correct password and username.
6368 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446369 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276370 EXPECT_EQ(ERR_IO_PENDING, rv);
6371 rv = callback4.WaitForResult();
6372 EXPECT_EQ(OK, rv);
6373 response = trans->GetResponseInfo();
6374 ASSERT_FALSE(response == NULL);
6375 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6376}
6377
[email protected]564b4912010-03-09 16:30:426378TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386379 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6380 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426381
[email protected]564b4912010-03-09 16:30:426382 SessionDependencies session_deps;
6383
6384 MockRead data_reads[] = {
6385 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356386 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426387 MockRead("hello world"),
6388 MockRead(false, OK),
6389 };
6390
6391 HttpRequestInfo request;
6392 request.method = "GET";
6393 request.url = GURL("http://www.google.com/");
6394 request.load_flags = 0;
6395
6396 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6397
6398 session_deps.socket_factory.AddSocketDataProvider(&data);
6399
6400 TestCompletionCallback callback;
6401
6402 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6403 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6404
[email protected]5a1d7ca2010-04-28 20:12:276405 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426406 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536407
[email protected]2fbaecf22010-07-22 22:20:356408 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426409 const HttpAlternateProtocols& alternate_protocols =
6410 session->alternate_protocols();
6411 EXPECT_FALSE(
6412 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6413
6414 EXPECT_EQ(OK, callback.WaitForResult());
6415
6416 const HttpResponseInfo* response = trans->GetResponseInfo();
6417 ASSERT_TRUE(response != NULL);
6418 ASSERT_TRUE(response->headers != NULL);
6419 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536420 EXPECT_FALSE(response->was_fetched_via_spdy);
6421 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576422 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]564b4912010-03-09 16:30:426423
6424 std::string response_data;
6425 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6426 EXPECT_EQ("hello world", response_data);
6427
6428 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6429 const HttpAlternateProtocols::PortProtocolPair alternate =
6430 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6431 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6432 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356433 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426434 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426435
[email protected]8e6441ca2010-08-19 05:56:386436 HttpStreamFactory::set_use_alternate_protocols(false);
6437 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426438}
6439
6440TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocol) {
[email protected]8e6441ca2010-08-19 05:56:386441 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426442 SessionDependencies session_deps;
6443
6444 HttpRequestInfo request;
6445 request.method = "GET";
6446 request.url = GURL("http://www.google.com/");
6447 request.load_flags = 0;
6448
6449 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6450 StaticSocketDataProvider first_data;
6451 first_data.set_connect_data(mock_connect);
6452 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6453
6454 MockRead data_reads[] = {
6455 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6456 MockRead("hello world"),
6457 MockRead(true, OK),
6458 };
6459 StaticSocketDataProvider second_data(
6460 data_reads, arraysize(data_reads), NULL, 0);
6461 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6462
6463 // TODO(willchan): Delete this extra data provider. It's necessary due to a
6464 // ClientSocketPoolBaseHelper bug that starts up too many ConnectJobs:
6465 // http://crbug.com/37454.
6466 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6467
6468 TestCompletionCallback callback;
6469
6470 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6471
[email protected]2fbaecf22010-07-22 22:20:356472 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426473 HttpAlternateProtocols* alternate_protocols =
6474 session->mutable_alternate_protocols();
6475 alternate_protocols->SetAlternateProtocolFor(
6476 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356477 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426478
6479 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6480
[email protected]5a1d7ca2010-04-28 20:12:276481 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426482 EXPECT_EQ(ERR_IO_PENDING, rv);
6483 EXPECT_EQ(OK, callback.WaitForResult());
6484
6485 const HttpResponseInfo* response = trans->GetResponseInfo();
6486 ASSERT_TRUE(response != NULL);
6487 ASSERT_TRUE(response->headers != NULL);
6488 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6489
6490 std::string response_data;
6491 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6492 EXPECT_EQ("hello world", response_data);
6493
6494 ASSERT_TRUE(
6495 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6496 const HttpAlternateProtocols::PortProtocolPair alternate =
6497 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6498 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386499 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426500}
6501
6502// TODO(willchan): Redo this test to use TLS/NPN=>SPDY. Currently, the code
6503// says that it does SPDY, but it just does the TLS handshake, but the NPN
6504// response does not indicate SPDY, so we just do standard HTTPS over the port.
6505// We should add code such that we don't fallback to HTTPS, but fallback to HTTP
6506// on the original port.
[email protected]a2cb8122010-03-10 17:22:426507// TEST_F(HttpNetworkTransactionTest, UseAlternateProtocol) {
6508// SessionDependencies session_deps;
[email protected]9e743cd2010-03-16 07:03:536509//
[email protected]a2cb8122010-03-10 17:22:426510// HttpRequestInfo request;
6511// request.method = "GET";
6512// request.url = GURL("http://www.google.com/");
6513// request.load_flags = 0;
[email protected]9e743cd2010-03-16 07:03:536514//
[email protected]a2cb8122010-03-10 17:22:426515// MockRead data_reads[] = {
6516// MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6517// MockRead("hello world"),
6518// MockRead(true, OK),
6519// };
6520// StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6521// session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]9e743cd2010-03-16 07:03:536522//
[email protected]a2cb8122010-03-10 17:22:426523// SSLSocketDataProvider ssl(true, OK);
6524// session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]9e743cd2010-03-16 07:03:536525//
[email protected]a2cb8122010-03-10 17:22:426526// TestCompletionCallback callback;
[email protected]9e743cd2010-03-16 07:03:536527//
[email protected]a2cb8122010-03-10 17:22:426528// scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]9e743cd2010-03-16 07:03:536529//
[email protected]a2cb8122010-03-10 17:22:426530// HostPortPair http_host_port_pair;
6531// http_host_port_pair.host = "www.google.com";
6532// http_host_port_pair.port = 80;
6533// HttpAlternateProtocols* alternate_protocols =
6534// session->mutable_alternate_protocols();
6535// alternate_protocols->SetAlternateProtocolFor(
6536// http_host_port_pair, 1234 /* port is ignored */,
[email protected]31e2c69e2010-04-15 18:06:066537// HttpAlternateProtocols::NPN_SPDY_1);
[email protected]9e743cd2010-03-16 07:03:536538//
[email protected]a2cb8122010-03-10 17:22:426539// scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]9e743cd2010-03-16 07:03:536540//
[email protected]5a1d7ca2010-04-28 20:12:276541// int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]a2cb8122010-03-10 17:22:426542// EXPECT_EQ(ERR_IO_PENDING, rv);
6543// EXPECT_EQ(OK, callback.WaitForResult());
[email protected]9e743cd2010-03-16 07:03:536544//
[email protected]a2cb8122010-03-10 17:22:426545// const HttpResponseInfo* response = trans->GetResponseInfo();
6546// ASSERT_TRUE(response != NULL);
6547// ASSERT_TRUE(response->headers != NULL);
6548// EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]9e743cd2010-03-16 07:03:536549//
[email protected]a2cb8122010-03-10 17:22:426550// std::string response_data;
6551// ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6552// EXPECT_EQ("hello world", response_data);
6553// }
6554
6555TEST_F(HttpNetworkTransactionTest, FailNpnSpdyAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386556 HttpStreamFactory::set_use_alternate_protocols(true);
6557 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]564b4912010-03-09 16:30:426558 SessionDependencies session_deps;
6559
6560 HttpRequestInfo request;
6561 request.method = "GET";
6562 request.url = GURL("http://www.google.com/");
6563 request.load_flags = 0;
6564
[email protected]a2cb8122010-03-10 17:22:426565 StaticSocketDataProvider first_tcp_connect;
6566 session_deps.socket_factory.AddSocketDataProvider(&first_tcp_connect);
6567
6568 SSLSocketDataProvider ssl(true, OK);
6569 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6570
[email protected]564b4912010-03-09 16:30:426571 MockRead data_reads[] = {
6572 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6573 MockRead("hello world"),
6574 MockRead(true, OK),
6575 };
[email protected]a2cb8122010-03-10 17:22:426576 StaticSocketDataProvider fallback_data(
6577 data_reads, arraysize(data_reads), NULL, 0);
6578 session_deps.socket_factory.AddSocketDataProvider(&fallback_data);
[email protected]564b4912010-03-09 16:30:426579
6580 TestCompletionCallback callback;
6581
6582 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6583
[email protected]2fbaecf22010-07-22 22:20:356584 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426585 HttpAlternateProtocols* alternate_protocols =
6586 session->mutable_alternate_protocols();
6587 alternate_protocols->SetAlternateProtocolFor(
6588 http_host_port_pair, 1234 /* port is ignored */,
[email protected]dae22c52010-07-30 02:16:356589 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426590
6591 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6592
[email protected]5a1d7ca2010-04-28 20:12:276593 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426594 EXPECT_EQ(ERR_IO_PENDING, rv);
6595 EXPECT_EQ(OK, callback.WaitForResult());
6596
6597 const HttpResponseInfo* response = trans->GetResponseInfo();
6598 ASSERT_TRUE(response != NULL);
6599 ASSERT_TRUE(response->headers != NULL);
6600 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6601
6602 std::string response_data;
6603 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6604 EXPECT_EQ("hello world", response_data);
[email protected]8e6441ca2010-08-19 05:56:386605 HttpStreamFactory::set_next_protos("");
6606 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546607}
6608
6609TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386610 HttpStreamFactory::set_use_alternate_protocols(true);
6611 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546612 SessionDependencies session_deps;
6613
6614 HttpRequestInfo request;
6615 request.method = "GET";
6616 request.url = GURL("http://www.google.com/");
6617 request.load_flags = 0;
6618
6619 MockRead data_reads[] = {
6620 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356621 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546622 MockRead("hello world"),
6623 MockRead(true, OK),
6624 };
6625
6626 StaticSocketDataProvider first_transaction(
6627 data_reads, arraysize(data_reads), NULL, 0);
6628 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6629
6630 SSLSocketDataProvider ssl(true, OK);
6631 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356632 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536633 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546634 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6635
[email protected]2bd93022010-07-17 00:58:446636 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136637 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546638
[email protected]2bd93022010-07-17 00:58:446639 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6640 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546641 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136642 CreateMockRead(*resp),
6643 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546644 MockRead(true, 0, 0),
6645 };
6646
6647 scoped_refptr<DelayedSocketData> spdy_data(
6648 new DelayedSocketData(
6649 1, // wait for one write to finish before reading.
6650 spdy_reads, arraysize(spdy_reads),
6651 spdy_writes, arraysize(spdy_writes)));
6652 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6653
6654 TestCompletionCallback callback;
6655
6656 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6657 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6658
[email protected]5a1d7ca2010-04-28 20:12:276659 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546660 EXPECT_EQ(ERR_IO_PENDING, rv);
6661 EXPECT_EQ(OK, callback.WaitForResult());
6662
6663 const HttpResponseInfo* response = trans->GetResponseInfo();
6664 ASSERT_TRUE(response != NULL);
6665 ASSERT_TRUE(response->headers != NULL);
6666 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6667
6668 std::string response_data;
6669 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6670 EXPECT_EQ("hello world", response_data);
6671
6672 trans.reset(new HttpNetworkTransaction(session));
6673
[email protected]5a1d7ca2010-04-28 20:12:276674 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546675 EXPECT_EQ(ERR_IO_PENDING, rv);
6676 EXPECT_EQ(OK, callback.WaitForResult());
6677
6678 response = trans->GetResponseInfo();
6679 ASSERT_TRUE(response != NULL);
6680 ASSERT_TRUE(response->headers != NULL);
6681 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536682 EXPECT_TRUE(response->was_fetched_via_spdy);
6683 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576684 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546685
6686 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6687 EXPECT_EQ("hello!", response_data);
6688
[email protected]8e6441ca2010-08-19 05:56:386689 HttpStreamFactory::set_next_protos("");
6690 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546691}
6692
[email protected]631f1322010-04-30 17:59:116693class CapturingProxyResolver : public ProxyResolver {
6694 public:
6695 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6696 virtual ~CapturingProxyResolver() {}
6697
6698 virtual int GetProxyForURL(const GURL& url,
6699 ProxyInfo* results,
6700 CompletionCallback* callback,
6701 RequestHandle* request,
6702 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406703 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6704 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426705 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116706 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426707 return OK;
[email protected]631f1322010-04-30 17:59:116708 }
6709
6710 virtual void CancelRequest(RequestHandle request) {
6711 NOTREACHED();
6712 }
6713
[email protected]1e605472010-12-16 21:41:406714 virtual void CancelSetPacScript() {
6715 NOTREACHED();
6716 }
6717
[email protected]24476402010-07-20 20:55:176718 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116719 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426720 return OK;
[email protected]631f1322010-04-30 17:59:116721 }
6722
[email protected]24476402010-07-20 20:55:176723 const std::vector<GURL>& resolved() const { return resolved_; }
6724
6725 private:
[email protected]631f1322010-04-30 17:59:116726 std::vector<GURL> resolved_;
6727
6728 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6729};
6730
[email protected]631f1322010-04-30 17:59:116731TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386732 HttpStreamFactory::set_use_alternate_protocols(true);
6733 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116734
6735 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426736 proxy_config.set_auto_detect(true);
6737 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116738
[email protected]631f1322010-04-30 17:59:116739 CapturingProxyResolver* capturing_proxy_resolver =
6740 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386741 SessionDependencies session_deps(new ProxyService(
6742 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6743 NULL));
[email protected]631f1322010-04-30 17:59:116744
6745 HttpRequestInfo request;
6746 request.method = "GET";
6747 request.url = GURL("http://www.google.com/");
6748 request.load_flags = 0;
6749
6750 MockRead data_reads[] = {
6751 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356752 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116753 MockRead("hello world"),
6754 MockRead(true, OK),
6755 };
6756
6757 StaticSocketDataProvider first_transaction(
6758 data_reads, arraysize(data_reads), NULL, 0);
6759 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6760
6761 SSLSocketDataProvider ssl(true, OK);
6762 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356763 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536764 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116765 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6766
[email protected]2bd93022010-07-17 00:58:446767 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116768 MockWrite spdy_writes[] = {
6769 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6770 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426771 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136772 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116773 };
6774
[email protected]d911f1b2010-05-05 22:39:426775 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6776
[email protected]2bd93022010-07-17 00:58:446777 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6778 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116779 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426780 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136781 CreateMockRead(*resp.get(), 4), // 2, 4
6782 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426783 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116784 };
6785
[email protected]d911f1b2010-05-05 22:39:426786 scoped_refptr<OrderedSocketData> spdy_data(
6787 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116788 spdy_reads, arraysize(spdy_reads),
6789 spdy_writes, arraysize(spdy_writes)));
6790 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6791
6792 TestCompletionCallback callback;
6793
6794 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6795 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6796
6797 int rv = trans->Start(&request, &callback, BoundNetLog());
6798 EXPECT_EQ(ERR_IO_PENDING, rv);
6799 EXPECT_EQ(OK, callback.WaitForResult());
6800
6801 const HttpResponseInfo* response = trans->GetResponseInfo();
6802 ASSERT_TRUE(response != NULL);
6803 ASSERT_TRUE(response->headers != NULL);
6804 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536805 EXPECT_FALSE(response->was_fetched_via_spdy);
6806 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116807
6808 std::string response_data;
6809 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6810 EXPECT_EQ("hello world", response_data);
6811
6812 trans.reset(new HttpNetworkTransaction(session));
6813
6814 rv = trans->Start(&request, &callback, BoundNetLog());
6815 EXPECT_EQ(ERR_IO_PENDING, rv);
6816 EXPECT_EQ(OK, callback.WaitForResult());
6817
6818 response = trans->GetResponseInfo();
6819 ASSERT_TRUE(response != NULL);
6820 ASSERT_TRUE(response->headers != NULL);
6821 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536822 EXPECT_TRUE(response->was_fetched_via_spdy);
6823 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116824
6825 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6826 EXPECT_EQ("hello!", response_data);
[email protected]d911f1b2010-05-05 22:39:426827 ASSERT_EQ(2u, capturing_proxy_resolver->resolved().size());
6828 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116829 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426830 EXPECT_EQ("https://www.google.com/",
6831 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116832
[email protected]8e6441ca2010-08-19 05:56:386833 HttpStreamFactory::set_next_protos("");
6834 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116835}
[email protected]631f1322010-04-30 17:59:116836
[email protected]2ff8b312010-04-26 22:20:546837TEST_F(HttpNetworkTransactionTest,
6838 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386839 HttpStreamFactory::set_use_alternate_protocols(true);
6840 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546841 SessionDependencies session_deps;
6842
6843 HttpRequestInfo request;
6844 request.method = "GET";
6845 request.url = GURL("http://www.google.com/");
6846 request.load_flags = 0;
6847
6848 MockRead data_reads[] = {
6849 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356850 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546851 MockRead("hello world"),
6852 MockRead(true, OK),
6853 };
6854
6855 StaticSocketDataProvider first_transaction(
6856 data_reads, arraysize(data_reads), NULL, 0);
6857 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6858
6859 SSLSocketDataProvider ssl(true, OK);
6860 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356861 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536862 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546863 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:536864 // Make sure we use ssl for spdy here.
6865 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:546866
[email protected]2bd93022010-07-17 00:58:446867 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136868 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546869
[email protected]2bd93022010-07-17 00:58:446870 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6871 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546872 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136873 CreateMockRead(*resp),
6874 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546875 MockRead(true, 0, 0),
6876 };
6877
6878 scoped_refptr<DelayedSocketData> spdy_data(
6879 new DelayedSocketData(
6880 1, // wait for one write to finish before reading.
6881 spdy_reads, arraysize(spdy_reads),
6882 spdy_writes, arraysize(spdy_writes)));
6883 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6884
6885 TestCompletionCallback callback;
6886
6887 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6888
6889 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6890
[email protected]5a1d7ca2010-04-28 20:12:276891 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546892 EXPECT_EQ(ERR_IO_PENDING, rv);
6893 EXPECT_EQ(OK, callback.WaitForResult());
6894
6895 const HttpResponseInfo* response = trans->GetResponseInfo();
6896 ASSERT_TRUE(response != NULL);
6897 ASSERT_TRUE(response->headers != NULL);
6898 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6899
6900 std::string response_data;
6901 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6902 EXPECT_EQ("hello world", response_data);
6903
6904 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:386905 HostPortPair host_port_pair("www.google.com", 443);
6906 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:546907 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:276908 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
6909 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:276910 scoped_refptr<TCPSocketParams> tcp_params(
6911 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:386912
6913 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
6914 EXPECT_EQ(ERR_IO_PENDING,
6915 connection->Init(host_port_pair.ToString(),tcp_params, LOWEST,
6916 &callback, session->tcp_socket_pool(),
6917 BoundNetLog()));
6918 EXPECT_EQ(OK, callback.WaitForResult());
6919
6920 SSLConfig ssl_config;
6921 session->ssl_config_service()->GetSSLConfig(&ssl_config);
6922 ClientSocket* socket = connection->release_socket();
[email protected]7ab5bbd12010-10-19 13:33:216923 socket = session->socket_factory()->CreateSSLClientSocket(
[email protected]822581d2010-12-16 17:27:156924 socket, HostPortPair("" , 443), ssl_config, NULL /* ssl_host_info */,
6925 session->cert_verifier());
[email protected]02b0c342010-09-25 21:09:386926 connection->set_socket(socket);
6927 EXPECT_EQ(ERR_IO_PENDING, socket->Connect(&callback));
6928 EXPECT_EQ(OK, callback.WaitForResult());
6929
6930 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(connection.release(),
6931 true, OK));
6932
[email protected]2ff8b312010-04-26 22:20:546933 trans.reset(new HttpNetworkTransaction(session));
6934
[email protected]5a1d7ca2010-04-28 20:12:276935 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546936 EXPECT_EQ(ERR_IO_PENDING, rv);
6937 EXPECT_EQ(OK, callback.WaitForResult());
6938
6939 response = trans->GetResponseInfo();
6940 ASSERT_TRUE(response != NULL);
6941 ASSERT_TRUE(response->headers != NULL);
6942 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536943 EXPECT_TRUE(response->was_fetched_via_spdy);
6944 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:576945 EXPECT_TRUE(response->was_alternate_protocol_available);
[email protected]2ff8b312010-04-26 22:20:546946
6947 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6948 EXPECT_EQ("hello!", response_data);
6949
[email protected]8e6441ca2010-08-19 05:56:386950 HttpStreamFactory::set_next_protos("");
6951 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426952}
6953
[email protected]044de0642010-06-17 10:42:156954// GenerateAuthToken is a mighty big test.
6955// It tests all permutation of GenerateAuthToken behavior:
6956// - Synchronous and Asynchronous completion.
6957// - OK or error on completion.
6958// - Direct connection, non-authenticating proxy, and authenticating proxy.
6959// - HTTP or HTTPS backend (to include proxy tunneling).
6960// - Non-authenticating and authenticating backend.
6961//
6962// In all, there are 44 reasonable permuations (for example, if there are
6963// problems generating an auth token for an authenticating proxy, we don't
6964// need to test all permutations of the backend server).
6965//
6966// The test proceeds by going over each of the configuration cases, and
6967// potentially running up to three rounds in each of the tests. The TestConfig
6968// specifies both the configuration for the test as well as the expectations
6969// for the results.
6970TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:506971 static const char kServer[] = "http://www.example.com";
6972 static const char kSecureServer[] = "https://www.example.com";
6973 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:156974 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
6975
6976 enum AuthTiming {
6977 AUTH_NONE,
6978 AUTH_SYNC,
6979 AUTH_ASYNC,
6980 };
6981
6982 const MockWrite kGet(
6983 "GET / HTTP/1.1\r\n"
6984 "Host: www.example.com\r\n"
6985 "Connection: keep-alive\r\n\r\n");
6986 const MockWrite kGetProxy(
6987 "GET http://www.example.com/ HTTP/1.1\r\n"
6988 "Host: www.example.com\r\n"
6989 "Proxy-Connection: keep-alive\r\n\r\n");
6990 const MockWrite kGetAuth(
6991 "GET / HTTP/1.1\r\n"
6992 "Host: www.example.com\r\n"
6993 "Connection: keep-alive\r\n"
6994 "Authorization: auth_token\r\n\r\n");
6995 const MockWrite kGetProxyAuth(
6996 "GET http://www.example.com/ HTTP/1.1\r\n"
6997 "Host: www.example.com\r\n"
6998 "Proxy-Connection: keep-alive\r\n"
6999 "Proxy-Authorization: auth_token\r\n\r\n");
7000 const MockWrite kGetAuthThroughProxy(
7001 "GET http://www.example.com/ HTTP/1.1\r\n"
7002 "Host: www.example.com\r\n"
7003 "Proxy-Connection: keep-alive\r\n"
7004 "Authorization: auth_token\r\n\r\n");
7005 const MockWrite kGetAuthWithProxyAuth(
7006 "GET http://www.example.com/ HTTP/1.1\r\n"
7007 "Host: www.example.com\r\n"
7008 "Proxy-Connection: keep-alive\r\n"
7009 "Proxy-Authorization: auth_token\r\n"
7010 "Authorization: auth_token\r\n\r\n");
7011 const MockWrite kConnect(
7012 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7013 "Host: www.example.com\r\n"
7014 "Proxy-Connection: keep-alive\r\n\r\n");
7015 const MockWrite kConnectProxyAuth(
7016 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7017 "Host: www.example.com\r\n"
7018 "Proxy-Connection: keep-alive\r\n"
7019 "Proxy-Authorization: auth_token\r\n\r\n");
7020
7021 const MockRead kSuccess(
7022 "HTTP/1.1 200 OK\r\n"
7023 "Content-Type: text/html; charset=iso-8859-1\r\n"
7024 "Content-Length: 3\r\n\r\n"
7025 "Yes");
7026 const MockRead kFailure(
7027 "Should not be called.");
7028 const MockRead kServerChallenge(
7029 "HTTP/1.1 401 Unauthorized\r\n"
7030 "WWW-Authenticate: Mock realm=server\r\n"
7031 "Content-Type: text/html; charset=iso-8859-1\r\n"
7032 "Content-Length: 14\r\n\r\n"
7033 "Unauthorized\r\n");
7034 const MockRead kProxyChallenge(
7035 "HTTP/1.1 407 Unauthorized\r\n"
7036 "Proxy-Authenticate: Mock realm=proxy\r\n"
7037 "Proxy-Connection: close\r\n"
7038 "Content-Type: text/html; charset=iso-8859-1\r\n"
7039 "Content-Length: 14\r\n\r\n"
7040 "Unauthorized\r\n");
7041 const MockRead kProxyConnected(
7042 "HTTP/1.1 200 Connection Established\r\n\r\n");
7043
7044 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7045 // no constructors, but the C++ compiler on Windows warns about
7046 // unspecified data in compound literals. So, moved to using constructors,
7047 // and TestRound's created with the default constructor should not be used.
7048 struct TestRound {
7049 TestRound()
7050 : expected_rv(ERR_UNEXPECTED),
7051 extra_write(NULL),
7052 extra_read(NULL) {
7053 }
7054 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7055 int expected_rv_arg)
7056 : write(write_arg),
7057 read(read_arg),
7058 expected_rv(expected_rv_arg),
7059 extra_write(NULL),
7060 extra_read(NULL) {
7061 }
7062 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7063 int expected_rv_arg, const MockWrite* extra_write_arg,
7064 const MockWrite* extra_read_arg)
7065 : write(write_arg),
7066 read(read_arg),
7067 expected_rv(expected_rv_arg),
7068 extra_write(extra_write_arg),
7069 extra_read(extra_read_arg) {
7070 }
7071 MockWrite write;
7072 MockRead read;
7073 int expected_rv;
7074 const MockWrite* extra_write;
7075 const MockRead* extra_read;
7076 };
7077
7078 static const int kNoSSL = 500;
7079
7080 struct TestConfig {
7081 const char* proxy_url;
7082 AuthTiming proxy_auth_timing;
7083 int proxy_auth_rv;
7084 const char* server_url;
7085 AuthTiming server_auth_timing;
7086 int server_auth_rv;
7087 int num_auth_rounds;
7088 int first_ssl_round;
7089 TestRound rounds[3];
7090 } test_configs[] = {
7091 // Non-authenticating HTTP server with a direct connection.
7092 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7093 { TestRound(kGet, kSuccess, OK)}},
7094 // Authenticating HTTP server with a direct connection.
7095 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7096 { TestRound(kGet, kServerChallenge, OK),
7097 TestRound(kGetAuth, kSuccess, OK)}},
7098 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7099 { TestRound(kGet, kServerChallenge, OK),
7100 TestRound(kGetAuth, kFailure, kAuthErr)}},
7101 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7102 { TestRound(kGet, kServerChallenge, OK),
7103 TestRound(kGetAuth, kSuccess, OK)}},
7104 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7105 { TestRound(kGet, kServerChallenge, OK),
7106 TestRound(kGetAuth, kFailure, kAuthErr)}},
7107 // Non-authenticating HTTP server through a non-authenticating proxy.
7108 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7109 { TestRound(kGetProxy, kSuccess, OK)}},
7110 // Authenticating HTTP server through a non-authenticating proxy.
7111 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7112 { TestRound(kGetProxy, kServerChallenge, OK),
7113 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7114 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7115 { TestRound(kGetProxy, kServerChallenge, OK),
7116 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7117 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7118 { TestRound(kGetProxy, kServerChallenge, OK),
7119 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7120 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7121 { TestRound(kGetProxy, kServerChallenge, OK),
7122 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7123 // Non-authenticating HTTP server through an authenticating proxy.
7124 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7125 { TestRound(kGetProxy, kProxyChallenge, OK),
7126 TestRound(kGetProxyAuth, kSuccess, OK)}},
7127 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7128 { TestRound(kGetProxy, kProxyChallenge, OK),
7129 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7130 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7131 { TestRound(kGetProxy, kProxyChallenge, OK),
7132 TestRound(kGetProxyAuth, kSuccess, OK)}},
7133 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7134 { TestRound(kGetProxy, kProxyChallenge, OK),
7135 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7136 // Authenticating HTTP server through an authenticating proxy.
7137 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7138 { TestRound(kGetProxy, kProxyChallenge, OK),
7139 TestRound(kGetProxyAuth, kServerChallenge, OK),
7140 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7141 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7142 { TestRound(kGetProxy, kProxyChallenge, OK),
7143 TestRound(kGetProxyAuth, kServerChallenge, OK),
7144 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7145 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7146 { TestRound(kGetProxy, kProxyChallenge, OK),
7147 TestRound(kGetProxyAuth, kServerChallenge, OK),
7148 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7149 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7150 { TestRound(kGetProxy, kProxyChallenge, OK),
7151 TestRound(kGetProxyAuth, kServerChallenge, OK),
7152 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7153 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7154 { TestRound(kGetProxy, kProxyChallenge, OK),
7155 TestRound(kGetProxyAuth, kServerChallenge, OK),
7156 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7157 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7158 { TestRound(kGetProxy, kProxyChallenge, OK),
7159 TestRound(kGetProxyAuth, kServerChallenge, OK),
7160 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7161 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7162 { TestRound(kGetProxy, kProxyChallenge, OK),
7163 TestRound(kGetProxyAuth, kServerChallenge, OK),
7164 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7165 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7166 { TestRound(kGetProxy, kProxyChallenge, OK),
7167 TestRound(kGetProxyAuth, kServerChallenge, OK),
7168 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7169 // Non-authenticating HTTPS server with a direct connection.
7170 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7171 { TestRound(kGet, kSuccess, OK)}},
7172 // Authenticating HTTPS server with a direct connection.
7173 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7174 { TestRound(kGet, kServerChallenge, OK),
7175 TestRound(kGetAuth, kSuccess, OK)}},
7176 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7177 { TestRound(kGet, kServerChallenge, OK),
7178 TestRound(kGetAuth, kFailure, kAuthErr)}},
7179 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7180 { TestRound(kGet, kServerChallenge, OK),
7181 TestRound(kGetAuth, kSuccess, OK)}},
7182 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7183 { TestRound(kGet, kServerChallenge, OK),
7184 TestRound(kGetAuth, kFailure, kAuthErr)}},
7185 // Non-authenticating HTTPS server with a non-authenticating proxy.
7186 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7187 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7188 // Authenticating HTTPS server through a non-authenticating proxy.
7189 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7190 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7191 TestRound(kGetAuth, kSuccess, OK)}},
7192 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7193 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7194 TestRound(kGetAuth, kFailure, kAuthErr)}},
7195 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7196 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7197 TestRound(kGetAuth, kSuccess, OK)}},
7198 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7199 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7200 TestRound(kGetAuth, kFailure, kAuthErr)}},
7201 // Non-Authenticating HTTPS server through an authenticating proxy.
7202 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7203 { TestRound(kConnect, kProxyChallenge, OK),
7204 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7205 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7206 { TestRound(kConnect, kProxyChallenge, OK),
7207 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7208 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7209 { TestRound(kConnect, kProxyChallenge, OK),
7210 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7211 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7212 { TestRound(kConnect, kProxyChallenge, OK),
7213 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7214 // Authenticating HTTPS server through an authenticating proxy.
7215 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7216 { TestRound(kConnect, kProxyChallenge, OK),
7217 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7218 &kGet, &kServerChallenge),
7219 TestRound(kGetAuth, kSuccess, OK)}},
7220 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7221 { TestRound(kConnect, kProxyChallenge, OK),
7222 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7223 &kGet, &kServerChallenge),
7224 TestRound(kGetAuth, kFailure, kAuthErr)}},
7225 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7226 { TestRound(kConnect, kProxyChallenge, OK),
7227 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7228 &kGet, &kServerChallenge),
7229 TestRound(kGetAuth, kSuccess, OK)}},
7230 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7231 { TestRound(kConnect, kProxyChallenge, OK),
7232 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7233 &kGet, &kServerChallenge),
7234 TestRound(kGetAuth, kFailure, kAuthErr)}},
7235 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7236 { TestRound(kConnect, kProxyChallenge, OK),
7237 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7238 &kGet, &kServerChallenge),
7239 TestRound(kGetAuth, kSuccess, OK)}},
7240 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7241 { TestRound(kConnect, kProxyChallenge, OK),
7242 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7243 &kGet, &kServerChallenge),
7244 TestRound(kGetAuth, kFailure, kAuthErr)}},
7245 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7246 { TestRound(kConnect, kProxyChallenge, OK),
7247 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7248 &kGet, &kServerChallenge),
7249 TestRound(kGetAuth, kSuccess, OK)}},
7250 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7251 { TestRound(kConnect, kProxyChallenge, OK),
7252 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7253 &kGet, &kServerChallenge),
7254 TestRound(kGetAuth, kFailure, kAuthErr)}},
7255 };
7256
7257 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007258 HttpAuthHandlerMock::Factory* auth_factory(
7259 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157260 session_deps.http_auth_handler_factory.reset(auth_factory);
7261
7262 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7263 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267264
7265 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157266 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007267 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157268 std::string auth_challenge = "Mock realm=proxy";
7269 GURL origin(test_config.proxy_url);
7270 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7271 auth_challenge.end());
7272 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7273 origin, BoundNetLog());
7274 auth_handler->SetGenerateExpectation(
7275 test_config.proxy_auth_timing == AUTH_ASYNC,
7276 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157277 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7278 }
7279 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007280 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157281 std::string auth_challenge = "Mock realm=server";
7282 GURL origin(test_config.server_url);
7283 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7284 auth_challenge.end());
7285 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7286 origin, BoundNetLog());
7287 auth_handler->SetGenerateExpectation(
7288 test_config.server_auth_timing == AUTH_ASYNC,
7289 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157290 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7291 }
7292 if (test_config.proxy_url) {
7293 session_deps.proxy_service =
[email protected]81cdfcd2010-10-16 00:49:007294 ProxyService::CreateFixed(test_config.proxy_url);
[email protected]044de0642010-06-17 10:42:157295 } else {
[email protected]ebeefff32010-09-15 05:10:027296 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]044de0642010-06-17 10:42:157297 }
7298
7299 HttpRequestInfo request;
7300 request.method = "GET";
7301 request.url = GURL(test_config.server_url);
7302 request.load_flags = 0;
7303
[email protected]0b0bf032010-09-21 18:08:507304 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7305 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157306
7307 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7308 const TestRound& read_write_round = test_config.rounds[round];
7309
7310 // Set up expected reads and writes.
7311 MockRead reads[2];
7312 reads[0] = read_write_round.read;
7313 size_t length_reads = 1;
7314 if (read_write_round.extra_read) {
7315 reads[1] = *read_write_round.extra_read;
7316 length_reads = 2;
7317 }
7318
7319 MockWrite writes[2];
7320 writes[0] = read_write_round.write;
7321 size_t length_writes = 1;
7322 if (read_write_round.extra_write) {
7323 writes[1] = *read_write_round.extra_write;
7324 length_writes = 2;
7325 }
7326 StaticSocketDataProvider data_provider(
7327 reads, length_reads, writes, length_writes);
7328 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7329
7330 // Add an SSL sequence if necessary.
7331 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7332 if (round >= test_config.first_ssl_round)
7333 session_deps.socket_factory.AddSSLSocketDataProvider(
7334 &ssl_socket_data_provider);
7335
7336 // Start or restart the transaction.
7337 TestCompletionCallback callback;
7338 int rv;
7339 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507340 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157341 } else {
[email protected]0b0bf032010-09-21 18:08:507342 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157343 }
7344 if (rv == ERR_IO_PENDING)
7345 rv = callback.WaitForResult();
7346
7347 // Compare results with expected data.
7348 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507349 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157350 if (read_write_round.expected_rv == OK) {
7351 EXPECT_FALSE(response == NULL);
7352 } else {
7353 EXPECT_TRUE(response == NULL);
7354 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7355 continue;
7356 }
7357 if (round + 1 < test_config.num_auth_rounds) {
7358 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7359 } else {
7360 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7361 }
7362 }
[email protected]e5ae96a2010-04-14 20:12:457363 }
7364}
7365
[email protected]c871bce92010-07-15 21:51:147366TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7367 // Do multi-round authentication and make sure it works correctly.
7368 SessionDependencies session_deps;
7369 HttpAuthHandlerMock::Factory* auth_factory(
7370 new HttpAuthHandlerMock::Factory());
7371 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]ebeefff32010-09-15 05:10:027372 session_deps.proxy_service = ProxyService::CreateDirect();
[email protected]c871bce92010-07-15 21:51:147373 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7374 session_deps.host_resolver->set_synchronous_mode(true);
7375
7376 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7377 auth_handler->set_connection_based(true);
7378 std::string auth_challenge = "Mock realm=server";
7379 GURL origin("http://www.example.com");
7380 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7381 auth_challenge.end());
7382 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7383 origin, BoundNetLog());
7384 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7385
[email protected]ad8e04a2010-11-01 04:16:277386 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]c871bce92010-07-15 21:51:147387 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7388
7389 int rv = OK;
7390 const HttpResponseInfo* response = NULL;
7391 HttpRequestInfo request;
7392 request.method = "GET";
7393 request.url = origin;
7394 request.load_flags = 0;
7395 TestCompletionCallback callback;
7396
7397 const MockWrite kGet(
7398 "GET / HTTP/1.1\r\n"
7399 "Host: www.example.com\r\n"
7400 "Connection: keep-alive\r\n\r\n");
7401 const MockWrite kGetAuth(
7402 "GET / HTTP/1.1\r\n"
7403 "Host: www.example.com\r\n"
7404 "Connection: keep-alive\r\n"
7405 "Authorization: auth_token\r\n\r\n");
7406
7407 const MockRead kServerChallenge(
7408 "HTTP/1.1 401 Unauthorized\r\n"
7409 "WWW-Authenticate: Mock realm=server\r\n"
7410 "Content-Type: text/html; charset=iso-8859-1\r\n"
7411 "Content-Length: 14\r\n\r\n"
7412 "Unauthorized\r\n");
7413 const MockRead kSuccess(
7414 "HTTP/1.1 200 OK\r\n"
7415 "Content-Type: text/html; charset=iso-8859-1\r\n"
7416 "Content-Length: 3\r\n\r\n"
7417 "Yes");
7418
7419 MockWrite writes[] = {
7420 // First round
7421 kGet,
7422 // Second round
7423 kGetAuth,
7424 // Third round
7425 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307426 // Fourth round
7427 kGetAuth
[email protected]c871bce92010-07-15 21:51:147428 };
7429 MockRead reads[] = {
7430 // First round
7431 kServerChallenge,
7432 // Second round
7433 kServerChallenge,
7434 // Third round
[email protected]eca50e122010-09-11 14:03:307435 kServerChallenge,
7436 // Fourth round
[email protected]c871bce92010-07-15 21:51:147437 kSuccess,
7438 };
7439 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7440 writes, arraysize(writes));
7441 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7442
7443 // First round
7444 auth_handler->SetGenerateExpectation(false, OK);
7445 rv = trans->Start(&request, &callback, BoundNetLog());
7446 if (rv == ERR_IO_PENDING)
7447 rv = callback.WaitForResult();
7448 EXPECT_EQ(OK, rv);
7449 response = trans->GetResponseInfo();
7450 ASSERT_FALSE(response == NULL);
7451 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7452
7453 // Second round
7454 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447455 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147456 if (rv == ERR_IO_PENDING)
7457 rv = callback.WaitForResult();
7458 EXPECT_EQ(OK, rv);
7459 response = trans->GetResponseInfo();
7460 ASSERT_FALSE(response == NULL);
7461 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7462
7463 // Third round
7464 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447465 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147466 if (rv == ERR_IO_PENDING)
7467 rv = callback.WaitForResult();
7468 EXPECT_EQ(OK, rv);
7469 response = trans->GetResponseInfo();
7470 ASSERT_FALSE(response == NULL);
7471 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]eca50e122010-09-11 14:03:307472
7473 // Fourth round
7474 auth_handler->SetGenerateExpectation(false, OK);
7475 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7476 if (rv == ERR_IO_PENDING)
7477 rv = callback.WaitForResult();
7478 EXPECT_EQ(OK, rv);
7479 response = trans->GetResponseInfo();
7480 ASSERT_FALSE(response == NULL);
7481 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]c871bce92010-07-15 21:51:147482}
7483
[email protected]aeaca1f2010-04-20 22:05:217484class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7485 public:
[email protected]06650c52010-06-03 00:49:177486 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217487 : fail_all_(fail_all) {
7488 }
7489
7490 virtual MockRead GetNextRead() {
7491 if (fail_all_)
7492 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7493
7494 return MockRead(false /* async */,
7495 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7496 }
7497
7498 virtual MockWriteResult OnWrite(const std::string& data) {
7499 return MockWriteResult(false /* async */, data.size());
7500 }
7501
7502 void Reset() {
7503 }
7504
7505 private:
7506 const bool fail_all_;
7507};
7508
7509// Test that we restart a connection when we see a decompression failure from
7510// the peer during the handshake. (In the real world we'll restart with SSLv3
7511// and we won't offer DEFLATE in that case.)
7512TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7513 HttpRequestInfo request;
7514 request.method = "GET";
7515 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7516 request.load_flags = 0;
7517
7518 SessionDependencies session_deps;
7519 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7520 false /* fail all reads */);
7521 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7522 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117523 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217524 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7525 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7526 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7527 session_deps.socket_factory.AddSSLSocketDataProvider(
7528 &ssl_socket_data_provider1);
7529 session_deps.socket_factory.AddSSLSocketDataProvider(
7530 &ssl_socket_data_provider2);
7531
[email protected]e60e47a2010-07-14 03:37:187532 // Work around http://crbug.com/37454
7533 StaticSocketDataProvider bug37454_connection;
7534 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7535 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7536
[email protected]aeaca1f2010-04-20 22:05:217537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7538 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7539 TestCompletionCallback callback;
7540
[email protected]5a1d7ca2010-04-28 20:12:277541 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217542 EXPECT_EQ(ERR_IO_PENDING, rv);
7543 EXPECT_EQ(OK, callback.WaitForResult());
7544
7545 const HttpResponseInfo* response = trans->GetResponseInfo();
7546 ASSERT_TRUE(response != NULL);
7547 ASSERT_TRUE(response->headers != NULL);
7548 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7549
7550 std::string response_data;
7551 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7552 EXPECT_EQ("ok.", response_data);
7553}
7554
7555// Test that we restart a connection if we get a decompression failure from the
7556// peer while reading the first bytes from the connection. This occurs when the
7557// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7558// in the handshake.
7559TEST_F(HttpNetworkTransactionTest,
7560 RestartAfterTLSDecompressionFailureWithFalseStart) {
7561 HttpRequestInfo request;
7562 request.method = "GET";
7563 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7564 request.load_flags = 0;
7565
7566 SessionDependencies session_deps;
7567 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7568 true /* fail all reads */);
7569 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7570 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7571 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7572 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7573 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7574 session_deps.socket_factory.AddSSLSocketDataProvider(
7575 &ssl_socket_data_provider1);
7576 session_deps.socket_factory.AddSSLSocketDataProvider(
7577 &ssl_socket_data_provider2);
7578
7579 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7580 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7581 TestCompletionCallback callback;
7582
[email protected]5a1d7ca2010-04-28 20:12:277583 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217584 EXPECT_EQ(ERR_IO_PENDING, rv);
7585 EXPECT_EQ(OK, callback.WaitForResult());
7586
7587 const HttpResponseInfo* response = trans->GetResponseInfo();
7588 ASSERT_TRUE(response != NULL);
7589 ASSERT_TRUE(response->headers != NULL);
7590 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7591
7592 std::string response_data;
7593 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7594 EXPECT_EQ("ok.", response_data);
7595}
7596
[email protected]65041fa2010-05-21 06:56:537597// This tests the case that a request is issued via http instead of spdy after
7598// npn is negotiated.
7599TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387600 HttpStreamFactory::set_use_alternate_protocols(true);
7601 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537602 SessionDependencies session_deps;
7603 HttpRequestInfo request;
7604 request.method = "GET";
7605 request.url = GURL("https://www.google.com/");
7606 request.load_flags = 0;
7607
7608 MockWrite data_writes[] = {
7609 MockWrite("GET / HTTP/1.1\r\n"
7610 "Host: www.google.com\r\n"
7611 "Connection: keep-alive\r\n\r\n"),
7612 };
7613
7614 MockRead data_reads[] = {
7615 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357616 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537617 MockRead("hello world"),
7618 MockRead(false, OK),
7619 };
7620
7621 SSLSocketDataProvider ssl(true, OK);
7622 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7623 ssl.next_proto = "http/1.1";
7624
7625 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7626
7627 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7628 data_writes, arraysize(data_writes));
7629 session_deps.socket_factory.AddSocketDataProvider(&data);
7630
7631 TestCompletionCallback callback;
7632
7633 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7634 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7635
7636 int rv = trans->Start(&request, &callback, BoundNetLog());
7637
7638 EXPECT_EQ(ERR_IO_PENDING, rv);
7639 EXPECT_EQ(OK, callback.WaitForResult());
7640
7641 const HttpResponseInfo* response = trans->GetResponseInfo();
7642 ASSERT_TRUE(response != NULL);
7643 ASSERT_TRUE(response->headers != NULL);
7644 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7645
7646 std::string response_data;
7647 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7648 EXPECT_EQ("hello world", response_data);
7649
7650 EXPECT_FALSE(response->was_fetched_via_spdy);
7651 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]193b0b892010-06-26 03:57:577652 EXPECT_FALSE(response->was_alternate_protocol_available);
[email protected]65041fa2010-05-21 06:56:537653
[email protected]8e6441ca2010-08-19 05:56:387654 HttpStreamFactory::set_next_protos("");
7655 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537656}
[email protected]26ef6582010-06-24 02:30:477657
7658TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7659 // Simulate the SSL handshake completing with an NPN negotiation
7660 // followed by an immediate server closing of the socket.
7661 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387662 HttpStreamFactory::set_use_alternate_protocols(true);
7663 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477664 SessionDependencies session_deps;
7665
7666 HttpRequestInfo request;
7667 request.method = "GET";
7668 request.url = GURL("https://www.google.com/");
7669 request.load_flags = 0;
7670
7671 SSLSocketDataProvider ssl(true, OK);
7672 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357673 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477674 ssl.was_npn_negotiated = true;
7675 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7676
[email protected]2bd93022010-07-17 00:58:447677 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137678 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477679
7680 MockRead spdy_reads[] = {
7681 MockRead(false, 0, 0) // Not async - return 0 immediately.
7682 };
7683
7684 scoped_refptr<DelayedSocketData> spdy_data(
7685 new DelayedSocketData(
7686 0, // don't wait in this case, immediate hangup.
7687 spdy_reads, arraysize(spdy_reads),
7688 spdy_writes, arraysize(spdy_writes)));
7689 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7690
7691 TestCompletionCallback callback;
7692
7693 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7694 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7695
7696 int rv = trans->Start(&request, &callback, BoundNetLog());
7697 EXPECT_EQ(ERR_IO_PENDING, rv);
7698 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7699
[email protected]8e6441ca2010-08-19 05:56:387700 HttpStreamFactory::set_next_protos("");
7701 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477702}
[email protected]65d34382010-07-01 18:12:267703
[email protected]f45c1ee2010-08-03 00:54:307704TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7705 // This test ensures that the URL passed into the proxy is upgraded
7706 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387707 HttpStreamFactory::set_use_alternate_protocols(true);
7708 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307709 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7710
[email protected]81cdfcd2010-10-16 00:49:007711 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307712 HttpAuthHandlerMock::Factory* auth_factory =
7713 new HttpAuthHandlerMock::Factory();
7714 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7715 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7716 auth_factory->set_do_init_from_challenge(true);
7717 session_deps.http_auth_handler_factory.reset(auth_factory);
7718
7719 HttpRequestInfo request;
7720 request.method = "GET";
7721 request.url = GURL("http://www.google.com");
7722 request.load_flags = 0;
7723
7724 // First round goes unauthenticated through the proxy.
7725 MockWrite data_writes_1[] = {
7726 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7727 "Host: www.google.com\r\n"
7728 "Proxy-Connection: keep-alive\r\n"
7729 "\r\n"),
7730 };
7731 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597732 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307733 MockRead("HTTP/1.1 200 OK\r\n"
7734 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7735 "Proxy-Connection: close\r\n"
7736 "\r\n"),
7737 };
7738 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7739 data_writes_1, arraysize(data_writes_1));
7740
7741 // Second round tries to tunnel to www.google.com due to the
7742 // Alternate-Protocol announcement in the first round. It fails due
7743 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597744 // After the failure, a tunnel is established to www.google.com using
7745 // Proxy-Authorization headers. There is then a SPDY request round.
7746 //
7747 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7748 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7749 // does a Disconnect and Connect on the same socket, rather than trying
7750 // to obtain a new one.
7751 //
7752 // NOTE: Originally, the proxy response to the second CONNECT request
7753 // simply returned another 407 so the unit test could skip the SSL connection
7754 // establishment and SPDY framing issues. Alas, the
7755 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307756 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597757
[email protected]f45c1ee2010-08-03 00:54:307758 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7759 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7760 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7761
[email protected]394816e92010-08-03 07:38:597762 MockWrite data_writes_2[] = {
7763 // First connection attempt without Proxy-Authorization.
7764 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7765 "Host: www.google.com\r\n"
7766 "Proxy-Connection: keep-alive\r\n"
7767 "\r\n"),
7768
7769 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307770 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7771 "Host: www.google.com\r\n"
7772 "Proxy-Connection: keep-alive\r\n"
7773 "Proxy-Authorization: auth_token\r\n"
7774 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307775
[email protected]394816e92010-08-03 07:38:597776 // SPDY request
7777 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307778 };
[email protected]394816e92010-08-03 07:38:597779 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7780 "Proxy-Authenticate: Mock\r\n"
7781 "Proxy-Connection: close\r\n"
7782 "\r\n");
7783 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7784 MockRead data_reads_2[] = {
7785 // First connection attempt fails
7786 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7787 MockRead(true, kRejectConnectResponse,
7788 arraysize(kRejectConnectResponse) - 1, 1),
7789
7790 // Second connection attempt passes
7791 MockRead(true, kAcceptConnectResponse,
7792 arraysize(kAcceptConnectResponse) -1, 4),
7793
7794 // SPDY response
7795 CreateMockRead(*resp.get(), 6),
7796 CreateMockRead(*data.get(), 6),
7797 MockRead(true, 0, 0, 6),
7798 };
7799 scoped_refptr<OrderedSocketData> data_2(
7800 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
7801 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:307802
7803 SSLSocketDataProvider ssl(true, OK);
7804 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7805 ssl.next_proto = "spdy/2";
7806 ssl.was_npn_negotiated = true;
7807
7808 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:597809 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:307810 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7811 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7812
7813 // First round should work and provide the Alternate-Protocol state.
7814 TestCompletionCallback callback_1;
7815 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
7816 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
7817 EXPECT_EQ(ERR_IO_PENDING, rv);
7818 EXPECT_EQ(OK, callback_1.WaitForResult());
7819
7820 // Second round should attempt a tunnel connect and get an auth challenge.
7821 TestCompletionCallback callback_2;
7822 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
7823 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
7824 EXPECT_EQ(ERR_IO_PENDING, rv);
7825 EXPECT_EQ(OK, callback_2.WaitForResult());
7826 const HttpResponseInfo* response = trans_2->GetResponseInfo();
7827 ASSERT_FALSE(response == NULL);
7828 ASSERT_FALSE(response->auth_challenge.get() == NULL);
7829
7830 // Restart with auth. Tunnel should work and response received.
7831 TestCompletionCallback callback_3;
7832 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
7833 EXPECT_EQ(ERR_IO_PENDING, rv);
7834 EXPECT_EQ(OK, callback_3.WaitForResult());
7835
7836 // After all that work, these two lines (or actually, just the scheme) are
7837 // what this test is all about. Make sure it happens correctly.
7838 const GURL& request_url = auth_handler->request_url();
7839 EXPECT_EQ("https", request_url.scheme());
7840 EXPECT_EQ("www.google.com", request_url.host());
7841
[email protected]8e6441ca2010-08-19 05:56:387842 HttpStreamFactory::set_next_protos("");
7843 HttpStreamFactory::set_use_alternate_protocols(false);
7844}
7845
7846// Test that if we cancel the transaction as the connection is completing, that
7847// everything tears down correctly.
7848TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
7849 // Setup everything about the connection to complete synchronously, so that
7850 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
7851 // for is the callback from the HttpStreamRequest.
7852 // Then cancel the transaction.
7853 // Verify that we don't crash.
7854 MockConnect mock_connect(false, OK);
7855 MockRead data_reads[] = {
7856 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
7857 MockRead(false, "hello world"),
7858 MockRead(false, OK),
7859 };
7860
7861 SessionDependencies session_deps;
7862 session_deps.host_resolver->set_synchronous_mode(true);
7863 scoped_ptr<HttpTransaction> trans(
7864 new HttpNetworkTransaction(CreateSession(&session_deps)));
7865
7866 HttpRequestInfo request;
7867 request.method = "GET";
7868 request.url = GURL("http://www.google.com/");
7869 request.load_flags = 0;
7870
7871 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
7872 data.set_connect_data(mock_connect);
7873 session_deps.socket_factory.AddSocketDataProvider(&data);
7874
7875 TestCompletionCallback callback;
7876
7877 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7878 int rv = trans->Start(&request, &callback, log.bound());
7879 EXPECT_EQ(ERR_IO_PENDING, rv);
7880 trans.reset(); // Cancel the transaction here.
7881
7882 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:307883}
7884
[email protected]76a505b2010-08-25 06:23:007885// Test a basic GET request through a proxy.
7886TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:007887 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007888 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7889 session_deps.net_log = log.bound().net_log();
7890 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7891
[email protected]76a505b2010-08-25 06:23:007892 HttpRequestInfo request;
7893 request.method = "GET";
7894 request.url = GURL("http://www.google.com/");
7895
7896 MockWrite data_writes1[] = {
7897 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7898 "Host: www.google.com\r\n"
7899 "Proxy-Connection: keep-alive\r\n\r\n"),
7900 };
7901
7902 MockRead data_reads1[] = {
7903 MockRead("HTTP/1.1 200 OK\r\n"),
7904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7905 MockRead("Content-Length: 100\r\n\r\n"),
7906 MockRead(false, OK),
7907 };
7908
7909 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7910 data_writes1, arraysize(data_writes1));
7911 session_deps.socket_factory.AddSocketDataProvider(&data1);
7912
7913 TestCompletionCallback callback1;
7914
[email protected]0b0bf032010-09-21 18:08:507915 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7916
[email protected]76a505b2010-08-25 06:23:007917 int rv = trans->Start(&request, &callback1, log.bound());
7918 EXPECT_EQ(ERR_IO_PENDING, rv);
7919
7920 rv = callback1.WaitForResult();
7921 EXPECT_EQ(OK, rv);
7922
7923 const HttpResponseInfo* response = trans->GetResponseInfo();
7924 ASSERT_FALSE(response == NULL);
7925
7926 EXPECT_TRUE(response->headers->IsKeepAlive());
7927 EXPECT_EQ(200, response->headers->response_code());
7928 EXPECT_EQ(100, response->headers->GetContentLength());
7929 EXPECT_TRUE(response->was_fetched_via_proxy);
7930 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7931}
7932
7933// Test a basic HTTPS GET request through a proxy.
7934TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:007935 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:007936 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
7937 session_deps.net_log = log.bound().net_log();
7938 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7939
[email protected]76a505b2010-08-25 06:23:007940 HttpRequestInfo request;
7941 request.method = "GET";
7942 request.url = GURL("https://www.google.com/");
7943
7944 // Since we have proxy, should try to establish tunnel.
7945 MockWrite data_writes1[] = {
7946 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7947 "Host: www.google.com\r\n"
7948 "Proxy-Connection: keep-alive\r\n\r\n"),
7949
7950 MockWrite("GET / HTTP/1.1\r\n"
7951 "Host: www.google.com\r\n"
7952 "Connection: keep-alive\r\n\r\n"),
7953 };
7954
7955 MockRead data_reads1[] = {
7956 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
7957
7958 MockRead("HTTP/1.1 200 OK\r\n"),
7959 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
7960 MockRead("Content-Length: 100\r\n\r\n"),
7961 MockRead(false, OK),
7962 };
7963
7964 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
7965 data_writes1, arraysize(data_writes1));
7966 session_deps.socket_factory.AddSocketDataProvider(&data1);
7967 SSLSocketDataProvider ssl(true, OK);
7968 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7969
7970 TestCompletionCallback callback1;
7971
[email protected]0b0bf032010-09-21 18:08:507972 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7973
[email protected]76a505b2010-08-25 06:23:007974 int rv = trans->Start(&request, &callback1, log.bound());
7975 EXPECT_EQ(ERR_IO_PENDING, rv);
7976
7977 rv = callback1.WaitForResult();
7978 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:407979 net::CapturingNetLog::EntryList entries;
7980 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:007981 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:407982 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:007983 NetLog::PHASE_NONE);
7984 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:407985 entries, pos,
[email protected]76a505b2010-08-25 06:23:007986 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
7987 NetLog::PHASE_NONE);
7988
7989 const HttpResponseInfo* response = trans->GetResponseInfo();
7990 ASSERT_FALSE(response == NULL);
7991
7992 EXPECT_TRUE(response->headers->IsKeepAlive());
7993 EXPECT_EQ(200, response->headers->response_code());
7994 EXPECT_EQ(100, response->headers->GetContentLength());
7995 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
7996 EXPECT_TRUE(response->was_fetched_via_proxy);
7997}
7998
7999// Test a basic HTTPS GET request through a proxy, but the server hangs up
8000// while establishing the tunnel.
8001TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008002 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008003 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8004 session_deps.net_log = log.bound().net_log();
8005 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8006
[email protected]76a505b2010-08-25 06:23:008007 HttpRequestInfo request;
8008 request.method = "GET";
8009 request.url = GURL("https://www.google.com/");
8010
8011 // Since we have proxy, should try to establish tunnel.
8012 MockWrite data_writes1[] = {
8013 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8014 "Host: www.google.com\r\n"
8015 "Proxy-Connection: keep-alive\r\n\r\n"),
8016
8017 MockWrite("GET / HTTP/1.1\r\n"
8018 "Host: www.google.com\r\n"
8019 "Connection: keep-alive\r\n\r\n"),
8020 };
8021
8022 MockRead data_reads1[] = {
8023 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8024 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8025 MockRead(true, 0, 0), // EOF
8026 };
8027
8028 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8029 data_writes1, arraysize(data_writes1));
8030 session_deps.socket_factory.AddSocketDataProvider(&data1);
8031 SSLSocketDataProvider ssl(true, OK);
8032 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8033
8034 TestCompletionCallback callback1;
8035
[email protected]0b0bf032010-09-21 18:08:508036 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8037
[email protected]76a505b2010-08-25 06:23:008038 int rv = trans->Start(&request, &callback1, log.bound());
8039 EXPECT_EQ(ERR_IO_PENDING, rv);
8040
8041 rv = callback1.WaitForResult();
8042 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408043 net::CapturingNetLog::EntryList entries;
8044 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008045 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408046 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008047 NetLog::PHASE_NONE);
8048 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408049 entries, pos,
[email protected]76a505b2010-08-25 06:23:008050 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8051 NetLog::PHASE_NONE);
8052}
8053
[email protected]749eefa82010-09-13 22:14:038054// Test for crbug.com/55424.
8055TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8056 SessionDependencies session_deps;
8057
8058 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8059 "https://www.google.com", false, 1, LOWEST));
8060 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8061
8062 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8063 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8064 MockRead spdy_reads[] = {
8065 CreateMockRead(*resp),
8066 CreateMockRead(*data),
8067 MockRead(true, 0, 0),
8068 };
8069
8070 scoped_refptr<DelayedSocketData> spdy_data(
8071 new DelayedSocketData(
8072 1, // wait for one write to finish before reading.
8073 spdy_reads, arraysize(spdy_reads),
8074 spdy_writes, arraysize(spdy_writes)));
8075 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8076
8077 SSLSocketDataProvider ssl(true, OK);
8078 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8079 ssl.next_proto = "spdy/2";
8080 ssl.was_npn_negotiated = true;
8081 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8082
8083 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8084
8085 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388086 HostPortPair host_port_pair("www.google.com", 443);
8087 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038088 scoped_refptr<SpdySession> spdy_session =
[email protected]f4580332010-09-25 21:20:278089 session->spdy_session_pool()->Get(pair, session->mutable_spdy_settings(),
8090 BoundNetLog());
[email protected]ad8e04a2010-11-01 04:16:278091 scoped_refptr<TCPSocketParams> tcp_params(
8092 new TCPSocketParams("www.google.com", 443, MEDIUM, GURL(), false));
[email protected]02b0c342010-09-25 21:09:388093 TestCompletionCallback callback;
8094
8095 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8096 EXPECT_EQ(ERR_IO_PENDING,
8097 connection->Init(host_port_pair.ToString(), tcp_params, LOWEST,
8098 &callback, session->tcp_socket_pool(),
8099 BoundNetLog()));
8100 EXPECT_EQ(OK, callback.WaitForResult());
8101 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038102
8103 HttpRequestInfo request;
8104 request.method = "GET";
8105 request.url = GURL("https://www.google.com/");
8106 request.load_flags = 0;
8107
8108 // This is the important line that marks this as a preconnect.
8109 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8110
8111 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8112
[email protected]749eefa82010-09-13 22:14:038113 int rv = trans->Start(&request, &callback, BoundNetLog());
8114 EXPECT_EQ(ERR_IO_PENDING, rv);
8115 EXPECT_EQ(OK, callback.WaitForResult());
8116}
8117
[email protected]73b8dd222010-11-11 19:55:248118// Given a net error, cause that error to be returned from the first Write()
8119// call and verify that the HttpTransaction fails with that error.
8120static void CheckErrorIsPassedBack(int error, bool async) {
8121 SessionDependencies session_deps;
8122
8123 SSLSocketDataProvider ssl_data(async, OK);
8124 net::MockWrite data_writes[] = {
8125 net::MockWrite(async, error),
8126 };
8127 net::StaticSocketDataProvider data(NULL, 0,
8128 data_writes, arraysize(data_writes));
8129 session_deps.socket_factory.AddSocketDataProvider(&data);
8130 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8131
8132 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8133 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8134
8135 net::HttpRequestInfo request_info;
8136 request_info.url = GURL("https://www.example.com/");
8137 request_info.method = "GET";
8138 request_info.load_flags = net::LOAD_NORMAL;
8139
8140 TestCompletionCallback callback;
8141 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8142 if (rv == net::ERR_IO_PENDING)
8143 rv = callback.WaitForResult();
8144 ASSERT_EQ(error, rv);
8145}
8146
8147TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8148 // Just check a grab bag of cert errors.
8149 static const int kErrors[] = {
8150 ERR_CERT_COMMON_NAME_INVALID,
8151 ERR_CERT_AUTHORITY_INVALID,
8152 ERR_CERT_DATE_INVALID,
8153 };
8154 for (size_t i = 0; i < arraysize(kErrors); i++) {
8155 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8156 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8157 }
8158}
8159
8160// Test that the transaction is restarted in the event of an NPN misprediction.
8161TEST_F(HttpNetworkTransactionTest, NPNMispredict) {
8162 SessionDependencies session_deps;
8163
8164 SSLSocketDataProvider ssl_data1(true /* async */, OK);
8165 SSLSocketDataProvider ssl_data2(true /* async */, OK);
8166
8167 net::MockWrite data1_writes[] = {
8168 net::MockWrite(true /* async */, ERR_SSL_SNAP_START_NPN_MISPREDICTION),
8169 };
8170 net::MockRead data2_reads[] = {
8171 net::MockRead("HTTP/1.0 200 OK\r\n\r\n"),
8172 net::MockRead("hello world"),
8173 net::MockRead(false, net::OK),
8174 };
8175 net::MockWrite data2_writes[] = {
8176 net::MockWrite("GET / HTTP/1.1\r\n"
8177 "Host: www.example.com\r\n"
8178 "Connection: keep-alive\r\n\r\n"),
8179 };
8180 net::StaticSocketDataProvider data1(
8181 NULL, 0, data1_writes, arraysize(data1_writes));
8182 net::StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads),
8183 data2_writes, arraysize(data2_writes));
8184
8185 session_deps.socket_factory.AddSocketDataProvider(&data1);
8186 session_deps.socket_factory.AddSocketDataProvider(&data2);
8187 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8188 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8189
8190 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8191 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8192
8193 net::HttpRequestInfo request_info;
8194 request_info.url = GURL("https://www.example.com/");
8195 request_info.method = "GET";
8196 request_info.load_flags = net::LOAD_NORMAL;
8197
8198 TestCompletionCallback callback;
8199 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8200 if (rv == net::ERR_IO_PENDING)
8201 rv = callback.WaitForResult();
8202 ASSERT_EQ(OK, rv);
8203
8204 std::string contents;
8205 rv = ReadTransaction(trans.get(), &contents);
8206 EXPECT_EQ(net::OK, rv);
8207 EXPECT_EQ("hello world", contents);
8208}
8209
[email protected]89ceba9a2009-03-21 03:46:068210} // namespace net