blob: 2a942dcaa9f3e810e434585d24ffa1b34969933f [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 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]3b63f8f42011-03-28 01:54:1514#include "base/memory/scoped_ptr.h"
[email protected]5e6efa52011-06-27 17:26:4115#include "base/metrics/histogram.h"
[email protected]be1ce6a72010-08-03 14:35:2216#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3517#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1218#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3319#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3220#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1221#include "net/base/net_log.h"
22#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3123#include "net/base/request_priority.h"
[email protected]bd0b6772011-01-11 19:59:3024#include "net/base/ssl_cert_request_info.h"
[email protected]db36938c2009-08-19 21:48:4225#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3326#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5227#include "net/base/test_completion_callback.h"
28#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1229#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0030#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2931#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5732#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4033#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5234#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5635#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5736#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3837#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5238#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5339#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1140#include "net/proxy/proxy_resolver.h"
41#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4442#include "net/socket/client_socket_factory.h"
43#include "net/socket/socket_test_util.h"
44#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5445#include "net/spdy/spdy_framer.h"
46#include "net/spdy/spdy_session.h"
47#include "net/spdy/spdy_session_pool.h"
48#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5249#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1550#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5251
52//-----------------------------------------------------------------------------
53
[email protected]13c8a092010-07-29 06:15:4454namespace {
55
56const string16 kBar(ASCIIToUTF16("bar"));
57const string16 kBar2(ASCIIToUTF16("bar2"));
58const string16 kBar3(ASCIIToUTF16("bar3"));
59const string16 kBaz(ASCIIToUTF16("baz"));
60const string16 kFirst(ASCIIToUTF16("first"));
61const string16 kFoo(ASCIIToUTF16("foo"));
62const string16 kFoo2(ASCIIToUTF16("foo2"));
63const string16 kFoo3(ASCIIToUTF16("foo3"));
64const string16 kFou(ASCIIToUTF16("fou"));
65const string16 kSecond(ASCIIToUTF16("second"));
66const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
67const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
68
69} // namespace
70
[email protected]89ceba9a2009-03-21 03:46:0671namespace net {
72
[email protected]e44de5d2009-06-05 20:12:4573// Helper to manage the lifetimes of the dependencies for a
74// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4475struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5976 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4277 SessionDependencies()
78 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1579 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:0280 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1081 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0882 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5483 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5484 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5985
86 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4587 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4288 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1589 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:4290 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1091 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0892 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5493 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5494 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5995
[email protected]73c45322010-10-01 23:57:5496 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:1597 scoped_ptr<CertVerifier> cert_verifier;
[email protected]6104ea5d2011-04-27 21:37:1298 scoped_ptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4299 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59100 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50101 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:54102 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59103};
104
[email protected]228ff742009-06-05 01:19:59105HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]9e1bdd32011-02-03 21:48:34106 net::HttpNetworkSession::Params params;
107 params.client_socket_factory = &session_deps->socket_factory;
108 params.host_resolver = session_deps->host_resolver.get();
109 params.cert_verifier = session_deps->cert_verifier.get();
[email protected]6104ea5d2011-04-27 21:37:12110 params.proxy_service = session_deps->proxy_service.get();
[email protected]9e1bdd32011-02-03 21:48:34111 params.ssl_config_service = session_deps->ssl_config_service;
112 params.http_auth_handler_factory =
113 session_deps->http_auth_handler_factory.get();
114 params.net_log = session_deps->net_log;
115 return new HttpNetworkSession(params);
[email protected]e8d536192008-10-17 22:21:14116}
117
[email protected]89836e22008-09-25 20:33:42118class HttpNetworkTransactionTest : public PlatformTest {
[email protected]e3ceb682011-06-28 23:55:46119 protected:
120 struct SimpleGetHelperResult {
121 int rv;
122 std::string status_line;
123 std::string response_data;
124 };
125
[email protected]2ff8b312010-04-26 22:20:54126 virtual void SetUp() {
[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(false);
130 }
131
[email protected]0e75a732008-10-16 20:36:09132 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50133 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
134 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54135 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09136 // Empty the current queue.
137 MessageLoop::current()->RunAllPending();
138 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50139 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
140 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09141 }
142
[email protected]3d2a59b2008-09-26 19:44:25143 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52144
[email protected]31a2bfe2010-02-09 08:03:39145 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
146 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15147 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52148
[email protected]ff007e162009-05-23 09:13:15149 HttpRequestInfo request;
150 request.method = "GET";
151 request.url = GURL("http://www.google.com/");
152 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]cb9bf6ca2011-01-28 13:15:27154 SessionDependencies session_deps;
155 scoped_ptr<HttpTransaction> trans(
156 new HttpNetworkTransaction(CreateSession(&session_deps)));
157
[email protected]31a2bfe2010-02-09 08:03:39158 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59159 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52160
[email protected]ff007e162009-05-23 09:13:15161 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52162
[email protected]169d0012010-05-10 23:20:12163 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40164 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12165 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15166 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52167
[email protected]ff007e162009-05-23 09:13:15168 out.rv = callback.WaitForResult();
169 if (out.rv != OK)
170 return out;
171
172 const HttpResponseInfo* response = trans->GetResponseInfo();
173 EXPECT_TRUE(response != NULL);
174
175 EXPECT_TRUE(response->headers != NULL);
176 out.status_line = response->headers->GetStatusLine();
177
[email protected]6d81b482011-02-22 19:47:19178 EXPECT_EQ("192.0.2.33", response->socket_address.host());
179 EXPECT_EQ(0, response->socket_address.port());
180
[email protected]ff007e162009-05-23 09:13:15181 rv = ReadTransaction(trans.get(), &out.response_data);
182 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40183
184 net::CapturingNetLog::EntryList entries;
185 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39186 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40187 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12188 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39189 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40190 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39191 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
192 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15193
[email protected]b2fcd0e2010-12-01 15:19:40194 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40195 NetLogHttpRequestParameter* request_params =
196 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
197 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
198 EXPECT_EQ("Host: www.google.com\r\n"
199 "Connection: keep-alive\r\n\r\n",
200 request_params->GetHeaders().ToString());
201
[email protected]aecfbf22008-10-16 02:02:47202 return out;
[email protected]ff007e162009-05-23 09:13:15203 }
initial.commit586acc5fe2008-07-26 22:42:52204
[email protected]ff007e162009-05-23 09:13:15205 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
206 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52207
[email protected]ff007e162009-05-23 09:13:15208 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15209};
[email protected]231d5a32008-09-13 00:45:27210
[email protected]15a5ccf82008-10-23 19:57:43211// Fill |str| with a long header list that consumes >= |size| bytes.
212void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19213 const char* row =
214 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
215 const int sizeof_row = strlen(row);
216 const int num_rows = static_cast<int>(
217 ceil(static_cast<float>(size) / sizeof_row));
218 const int sizeof_data = num_rows * sizeof_row;
219 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43220 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51221
[email protected]4ddaf2502008-10-23 18:26:19222 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43223 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19224}
225
[email protected]385a4672009-03-11 22:21:29226// Alternative functions that eliminate randomness and dependency on the local
227// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20228void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29229 static const uint8 bytes[] = {
230 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
231 };
232 static size_t current_byte = 0;
233 for (size_t i = 0; i < n; ++i) {
234 output[i] = bytes[current_byte++];
235 current_byte %= arraysize(bytes);
236 }
237}
238
[email protected]fe2bc6a2009-03-23 16:52:20239void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29240 static const uint8 bytes[] = {
241 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
242 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
243 };
244 static size_t current_byte = 0;
245 for (size_t i = 0; i < n; ++i) {
246 output[i] = bytes[current_byte++];
247 current_byte %= arraysize(bytes);
248 }
249}
250
[email protected]fe2bc6a2009-03-23 16:52:20251std::string MockGetHostName() {
252 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29253}
254
[email protected]e60e47a2010-07-14 03:37:18255template<typename ParentPool>
256class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31257 public:
[email protected]9e1bdd32011-02-03 21:48:34258 CaptureGroupNameSocketPool(HostResolver* host_resolver,
259 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18260
[email protected]d80a4322009-08-14 07:07:49261 const std::string last_group_name_received() const {
262 return last_group_name_;
263 }
264
[email protected]684970b2009-08-14 04:54:46265 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49266 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31267 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31268 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46269 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53270 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31271 last_group_name_ = group_name;
272 return ERR_IO_PENDING;
273 }
[email protected]04e5be32009-06-26 20:00:31274 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21275 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31276 virtual void ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10277 StreamSocket* socket,
[email protected]9f95c692011-02-11 19:20:19278 int id) {}
[email protected]04e5be32009-06-26 20:00:31279 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31280 virtual int IdleSocketCount() const {
281 return 0;
282 }
283 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
284 return 0;
285 }
286 virtual LoadState GetLoadState(const std::string& group_name,
287 const ClientSocketHandle* handle) const {
288 return LOAD_STATE_IDLE;
289 }
[email protected]a796bcec2010-03-22 17:17:26290 virtual base::TimeDelta ConnectionTimeout() const {
291 return base::TimeDelta();
292 }
[email protected]d80a4322009-08-14 07:07:49293
294 private:
[email protected]04e5be32009-06-26 20:00:31295 std::string last_group_name_;
296};
297
[email protected]ab739042011-04-07 15:22:28298typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
299CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13300typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
301CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06302typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11303CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18304typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
305CaptureGroupNameSSLSocketPool;
306
307template<typename ParentPool>
308CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34309 HostResolver* host_resolver,
310 CertVerifier* /* cert_verifier */)
311 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18312
313template<>
[email protected]2df19bb2010-08-25 20:13:46314CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34315 HostResolver* host_resolver,
316 CertVerifier* /* cert_verifier */)
317 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
[email protected]2df19bb2010-08-25 20:13:46318
319template<>
[email protected]e60e47a2010-07-14 03:37:18320CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34321 HostResolver* host_resolver,
322 CertVerifier* cert_verifier)
323 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
[email protected]feb79bcd2011-07-21 16:55:17324 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11325
[email protected]231d5a32008-09-13 00:45:27326//-----------------------------------------------------------------------------
327
[email protected]dae22c52010-07-30 02:16:35328// This is the expected list of advertised protocols from the browser's NPN
329// list.
330static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
331
332// This is the expected return from a current server advertising SPDY.
333static const char kAlternateProtocolHttpHeader[] =
334 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
335
[email protected]5e6efa52011-06-27 17:26:41336TEST_F(HttpNetworkTransactionTest, LogNumRttVsBytesMetrics_WarmestSocket) {
337 MockRead data_reads[1000];
338 data_reads[0] = MockRead("HTTP/1.0 200 OK\r\n\r\n");
339 for (int i = 1; i < 999; i++) {
340 data_reads[i] = MockRead("Gagan is a good boy!");
341 }
342 data_reads[999] = MockRead(false, OK);
343
344 net::SetSocketReusePolicy(0);
345 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
346 arraysize(data_reads));
347
348 base::Histogram* histogram = NULL;
349 base::StatisticsRecorder::FindHistogram(
350 "Net.Num_RTT_vs_KB_warmest_socket_15KB", &histogram);
351 CHECK(histogram);
352
353 base::Histogram::SampleSet sample_set;
354 histogram->SnapshotSample(&sample_set);
355 EXPECT_EQ(1, sample_set.TotalCount());
356
357 EXPECT_EQ(OK, out.rv);
358 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
359}
360
361// TODO(gagansingh): Add test for LogNumRttVsBytesMetrics_LastAccessSocket once
362// it is possible to clear histograms from previous tests.
363
[email protected]231d5a32008-09-13 00:45:27364TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59365 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40366 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43367 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27368}
369
370TEST_F(HttpNetworkTransactionTest, SimpleGET) {
371 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35372 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
373 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42374 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27375 };
[email protected]31a2bfe2010-02-09 08:03:39376 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
377 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42378 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27379 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
380 EXPECT_EQ("hello world", out.response_data);
381}
382
383// Response with no status line.
384TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
385 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35386 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42387 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27388 };
[email protected]31a2bfe2010-02-09 08:03:39389 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
390 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42391 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27392 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
393 EXPECT_EQ("hello world", out.response_data);
394}
395
396// Allow up to 4 bytes of junk to precede status line.
397TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
398 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35399 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42400 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27401 };
[email protected]31a2bfe2010-02-09 08:03:39402 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
403 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42404 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27405 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
406 EXPECT_EQ("DATA", out.response_data);
407}
408
409// Allow up to 4 bytes of junk to precede status line.
410TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
411 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35412 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42413 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27414 };
[email protected]31a2bfe2010-02-09 08:03:39415 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
416 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42417 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27418 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
419 EXPECT_EQ("DATA", out.response_data);
420}
421
422// Beyond 4 bytes of slop and it should fail to find a status line.
423TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
424 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35425 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42426 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27427 };
[email protected]31a2bfe2010-02-09 08:03:39428 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
429 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42430 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25431 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
432 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27433}
434
435// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
436TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
437 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35438 MockRead("\n"),
439 MockRead("\n"),
440 MockRead("Q"),
441 MockRead("J"),
442 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42443 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27444 };
[email protected]31a2bfe2010-02-09 08:03:39445 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
446 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42447 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27448 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
449 EXPECT_EQ("DATA", out.response_data);
450}
451
452// Close the connection before enough bytes to have a status line.
453TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
454 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35455 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42456 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27457 };
[email protected]31a2bfe2010-02-09 08:03:39458 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
459 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42460 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27461 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
462 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52463}
464
[email protected]f9d44aa2008-09-23 23:57:17465// Simulate a 204 response, lacking a Content-Length header, sent over a
466// persistent connection. The response should still terminate since a 204
467// cannot have a response body.
468TEST_F(HttpNetworkTransactionTest, StopsReading204) {
469 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35470 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
471 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42472 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17473 };
[email protected]31a2bfe2010-02-09 08:03:39474 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
475 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42476 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17477 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
478 EXPECT_EQ("", out.response_data);
479}
480
[email protected]0877e3d2009-10-17 22:29:57481// A simple request using chunked encoding with some extra data after.
482// (Like might be seen in a pipelined response.)
483TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
484 MockRead data_reads[] = {
485 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
486 MockRead("5\r\nHello\r\n"),
487 MockRead("1\r\n"),
488 MockRead(" \r\n"),
489 MockRead("5\r\nworld\r\n"),
490 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
491 MockRead(false, OK),
492 };
[email protected]31a2bfe2010-02-09 08:03:39493 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
494 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57495 EXPECT_EQ(OK, out.rv);
496 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
497 EXPECT_EQ("Hello world", out.response_data);
498}
499
[email protected]9fe44f52010-09-23 18:36:00500// Next tests deal with http://crbug.com/56344.
501
502TEST_F(HttpNetworkTransactionTest,
503 MultipleContentLengthHeadersNoTransferEncoding) {
504 MockRead data_reads[] = {
505 MockRead("HTTP/1.1 200 OK\r\n"),
506 MockRead("Content-Length: 10\r\n"),
507 MockRead("Content-Length: 5\r\n\r\n"),
508 };
509 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
510 arraysize(data_reads));
511 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
512}
513
514TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04515 DuplicateContentLengthHeadersNoTransferEncoding) {
516 MockRead data_reads[] = {
517 MockRead("HTTP/1.1 200 OK\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.1 200 OK", out.status_line);
526 EXPECT_EQ("Hello", out.response_data);
527}
528
529TEST_F(HttpNetworkTransactionTest,
530 ComplexContentLengthHeadersNoTransferEncoding) {
531 // More than 2 dupes.
532 {
533 MockRead data_reads[] = {
534 MockRead("HTTP/1.1 200 OK\r\n"),
535 MockRead("Content-Length: 5\r\n"),
536 MockRead("Content-Length: 5\r\n"),
537 MockRead("Content-Length: 5\r\n\r\n"),
538 MockRead("Hello"),
539 };
540 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
541 arraysize(data_reads));
542 EXPECT_EQ(OK, out.rv);
543 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
544 EXPECT_EQ("Hello", out.response_data);
545 }
546 // HTTP/1.0
547 {
548 MockRead data_reads[] = {
549 MockRead("HTTP/1.0 200 OK\r\n"),
550 MockRead("Content-Length: 5\r\n"),
551 MockRead("Content-Length: 5\r\n"),
552 MockRead("Content-Length: 5\r\n\r\n"),
553 MockRead("Hello"),
554 };
555 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
556 arraysize(data_reads));
557 EXPECT_EQ(OK, out.rv);
558 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
559 EXPECT_EQ("Hello", out.response_data);
560 }
561 // 2 dupes and one mismatched.
562 {
563 MockRead data_reads[] = {
564 MockRead("HTTP/1.1 200 OK\r\n"),
565 MockRead("Content-Length: 10\r\n"),
566 MockRead("Content-Length: 10\r\n"),
567 MockRead("Content-Length: 5\r\n\r\n"),
568 };
569 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
570 arraysize(data_reads));
571 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
572 }
573}
574
575TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00576 MultipleContentLengthHeadersTransferEncoding) {
577 MockRead data_reads[] = {
578 MockRead("HTTP/1.1 200 OK\r\n"),
579 MockRead("Content-Length: 666\r\n"),
580 MockRead("Content-Length: 1337\r\n"),
581 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
582 MockRead("5\r\nHello\r\n"),
583 MockRead("1\r\n"),
584 MockRead(" \r\n"),
585 MockRead("5\r\nworld\r\n"),
586 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
587 MockRead(false, OK),
588 };
589 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
590 arraysize(data_reads));
591 EXPECT_EQ(OK, out.rv);
592 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
593 EXPECT_EQ("Hello world", out.response_data);
594}
595
[email protected]ef0faf2e72009-03-05 23:27:23596// Do a request using the HEAD method. Verify that we don't try to read the
597// message body (since HEAD has none).
598TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42599 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23600 request.method = "HEAD";
601 request.url = GURL("http://www.google.com/");
602 request.load_flags = 0;
603
[email protected]cb9bf6ca2011-01-28 13:15:27604 SessionDependencies session_deps;
605 scoped_ptr<HttpTransaction> trans(
606 new HttpNetworkTransaction(CreateSession(&session_deps)));
607
[email protected]ef0faf2e72009-03-05 23:27:23608 MockWrite data_writes1[] = {
609 MockWrite("HEAD / HTTP/1.1\r\n"
610 "Host: www.google.com\r\n"
611 "Connection: keep-alive\r\n"
612 "Content-Length: 0\r\n\r\n"),
613 };
614 MockRead data_reads1[] = {
615 MockRead("HTTP/1.1 404 Not Found\r\n"),
616 MockRead("Server: Blah\r\n"),
617 MockRead("Content-Length: 1234\r\n\r\n"),
618
619 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42620 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23621 };
622
[email protected]31a2bfe2010-02-09 08:03:39623 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
624 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59625 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23626
627 TestCompletionCallback callback1;
628
[email protected]5a1d7ca2010-04-28 20:12:27629 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42630 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23631
632 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42633 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23634
[email protected]1c773ea12009-04-28 19:58:42635 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23636 EXPECT_FALSE(response == NULL);
637
638 // Check that the headers got parsed.
639 EXPECT_TRUE(response->headers != NULL);
640 EXPECT_EQ(1234, response->headers->GetContentLength());
641 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
642
643 std::string server_header;
644 void* iter = NULL;
645 bool has_server_header = response->headers->EnumerateHeader(
646 &iter, "Server", &server_header);
647 EXPECT_TRUE(has_server_header);
648 EXPECT_EQ("Blah", server_header);
649
650 // Reading should give EOF right away, since there is no message body
651 // (despite non-zero content-length).
652 std::string response_data;
653 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42654 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23655 EXPECT_EQ("", response_data);
656}
657
initial.commit586acc5fe2008-07-26 22:42:52658TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59659 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52661
662 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35663 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
664 MockRead("hello"),
665 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
666 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42667 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52668 };
[email protected]31a2bfe2010-02-09 08:03:39669 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59670 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52671
[email protected]0b0bf032010-09-21 18:08:50672 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52673 "hello", "world"
674 };
675
676 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42677 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52678 request.method = "GET";
679 request.url = GURL("http://www.google.com/");
680 request.load_flags = 0;
681
[email protected]cb9bf6ca2011-01-28 13:15:27682 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
683
initial.commit586acc5fe2008-07-26 22:42:52684 TestCompletionCallback callback;
685
[email protected]5a1d7ca2010-04-28 20:12:27686 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42687 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52688
689 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42690 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52691
[email protected]1c773ea12009-04-28 19:58:42692 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52693 EXPECT_TRUE(response != NULL);
694
695 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25696 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52697
698 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57699 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42700 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25701 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52702 }
703}
704
705TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42706 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52707 request.method = "POST";
708 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42709 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52710 request.upload_data->AppendBytes("foo", 3);
711 request.load_flags = 0;
712
[email protected]cb9bf6ca2011-01-28 13:15:27713 SessionDependencies session_deps;
714 scoped_ptr<HttpTransaction> trans(
715 new HttpNetworkTransaction(CreateSession(&session_deps)));
716
initial.commit586acc5fe2008-07-26 22:42:52717 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35718 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
719 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
720 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42721 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52722 };
[email protected]31a2bfe2010-02-09 08:03:39723 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59724 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52725
726 TestCompletionCallback callback;
727
[email protected]5a1d7ca2010-04-28 20:12:27728 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42729 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52730
731 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42732 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52733
[email protected]1c773ea12009-04-28 19:58:42734 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52735 EXPECT_TRUE(response != NULL);
736
737 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25738 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52739
740 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57741 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42742 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25743 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52744}
745
[email protected]3a2d3662009-03-27 03:49:14746// This test is almost the same as Ignores100 above, but the response contains
747// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57748// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14749TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42750 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14751 request.method = "GET";
752 request.url = GURL("http://www.foo.com/");
753 request.load_flags = 0;
754
[email protected]cb9bf6ca2011-01-28 13:15:27755 SessionDependencies session_deps;
756 scoped_ptr<HttpTransaction> trans(
757 new HttpNetworkTransaction(CreateSession(&session_deps)));
758
[email protected]3a2d3662009-03-27 03:49:14759 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57760 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
761 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14762 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42763 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14764 };
[email protected]31a2bfe2010-02-09 08:03:39765 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59766 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14767
768 TestCompletionCallback callback;
769
[email protected]5a1d7ca2010-04-28 20:12:27770 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42771 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14772
773 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42774 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14775
[email protected]1c773ea12009-04-28 19:58:42776 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14777 EXPECT_TRUE(response != NULL);
778
779 EXPECT_TRUE(response->headers != NULL);
780 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
781
782 std::string response_data;
783 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42784 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14785 EXPECT_EQ("hello world", response_data);
786}
787
[email protected]ee9410e72010-01-07 01:42:38788TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38789 HttpRequestInfo request;
790 request.method = "POST";
791 request.url = GURL("http://www.foo.com/");
792 request.load_flags = 0;
793
[email protected]cb9bf6ca2011-01-28 13:15:27794 SessionDependencies session_deps;
795 scoped_ptr<HttpTransaction> trans(
796 new HttpNetworkTransaction(CreateSession(&session_deps)));
797
[email protected]ee9410e72010-01-07 01:42:38798 MockRead data_reads[] = {
799 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
800 MockRead(true, 0),
801 };
[email protected]31a2bfe2010-02-09 08:03:39802 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38803 session_deps.socket_factory.AddSocketDataProvider(&data);
804
805 TestCompletionCallback callback;
806
[email protected]5a1d7ca2010-04-28 20:12:27807 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38808 EXPECT_EQ(ERR_IO_PENDING, rv);
809
810 rv = callback.WaitForResult();
811 EXPECT_EQ(OK, rv);
812
813 std::string response_data;
814 rv = ReadTransaction(trans.get(), &response_data);
815 EXPECT_EQ(OK, rv);
816 EXPECT_EQ("", response_data);
817}
818
819TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38820 HttpRequestInfo request;
821 request.method = "POST";
822 request.url = GURL("http://www.foo.com/");
823 request.load_flags = 0;
824
[email protected]cb9bf6ca2011-01-28 13:15:27825 SessionDependencies session_deps;
826 scoped_ptr<HttpTransaction> trans(
827 new HttpNetworkTransaction(CreateSession(&session_deps)));
828
[email protected]ee9410e72010-01-07 01:42:38829 MockRead data_reads[] = {
830 MockRead(true, 0),
831 };
[email protected]31a2bfe2010-02-09 08:03:39832 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38833 session_deps.socket_factory.AddSocketDataProvider(&data);
834
835 TestCompletionCallback callback;
836
[email protected]5a1d7ca2010-04-28 20:12:27837 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38838 EXPECT_EQ(ERR_IO_PENDING, rv);
839
840 rv = callback.WaitForResult();
841 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
842}
843
[email protected]3d2a59b2008-09-26 19:44:25844// read_failure specifies a read failure that should cause the network
845// transaction to resend the request.
846void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
847 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:42848 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52849 request.method = "GET";
850 request.url = GURL("http://www.foo.com/");
851 request.load_flags = 0;
852
[email protected]cb9bf6ca2011-01-28 13:15:27853 SessionDependencies session_deps;
854 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
855
initial.commit586acc5fe2008-07-26 22:42:52856 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35857 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
858 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25859 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52860 };
[email protected]31a2bfe2010-02-09 08:03:39861 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59862 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52863
864 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35865 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
866 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42867 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52868 };
[email protected]31a2bfe2010-02-09 08:03:39869 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59870 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52871
872 const char* kExpectedResponseData[] = {
873 "hello", "world"
874 };
875
876 for (int i = 0; i < 2; ++i) {
877 TestCompletionCallback callback;
878
[email protected]5695b8c2009-09-30 21:36:43879 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52880
[email protected]5a1d7ca2010-04-28 20:12:27881 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42882 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52883
884 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42885 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52886
[email protected]1c773ea12009-04-28 19:58:42887 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52888 EXPECT_TRUE(response != NULL);
889
890 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25891 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52892
893 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57894 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42895 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25896 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52897 }
898}
[email protected]3d2a59b2008-09-26 19:44:25899
900TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42901 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25902 KeepAliveConnectionResendRequestTest(read_failure);
903}
904
905TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42906 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25907 KeepAliveConnectionResendRequestTest(read_failure);
908}
909
910TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42911 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25912 request.method = "GET";
913 request.url = GURL("http://www.google.com/");
914 request.load_flags = 0;
915
[email protected]cb9bf6ca2011-01-28 13:15:27916 SessionDependencies session_deps;
917 scoped_ptr<HttpTransaction> trans(
918 new HttpNetworkTransaction(CreateSession(&session_deps)));
919
[email protected]3d2a59b2008-09-26 19:44:25920 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42921 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35922 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
923 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42924 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25925 };
[email protected]31a2bfe2010-02-09 08:03:39926 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59927 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25928
929 TestCompletionCallback callback;
930
[email protected]5a1d7ca2010-04-28 20:12:27931 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42932 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25933
934 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42935 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25936
[email protected]1c773ea12009-04-28 19:58:42937 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25938 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25939}
940
941// What do various browsers do when the server closes a non-keepalive
942// connection without sending any response header or body?
943//
944// IE7: error page
945// Safari 3.1.2 (Windows): error page
946// Firefox 3.0.1: blank page
947// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42948// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
949// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25950TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
951 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42952 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35953 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
954 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42955 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25956 };
[email protected]31a2bfe2010-02-09 08:03:39957 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
958 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42959 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25960}
[email protected]038e9a32008-10-08 22:40:16961
[email protected]0b0bf032010-09-21 18:08:50962// Test that we correctly reuse a keep-alive connection after not explicitly
963// reading the body.
964TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13965 HttpRequestInfo request;
966 request.method = "GET";
967 request.url = GURL("http://www.foo.com/");
968 request.load_flags = 0;
969
[email protected]cb9bf6ca2011-01-28 13:15:27970 SessionDependencies session_deps;
971 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
972
[email protected]0b0bf032010-09-21 18:08:50973 // Note that because all these reads happen in the same
974 // StaticSocketDataProvider, it shows that the same socket is being reused for
975 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13976 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50977 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
978 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13979 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50980 MockRead("HTTP/1.1 302 Found\r\n"
981 "Content-Length: 0\r\n\r\n"),
982 MockRead("HTTP/1.1 302 Found\r\n"
983 "Content-Length: 5\r\n\r\n"
984 "hello"),
985 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
986 "Content-Length: 0\r\n\r\n"),
987 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
988 "Content-Length: 5\r\n\r\n"
989 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13990 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
991 MockRead("hello"),
992 };
993 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
994 session_deps.socket_factory.AddSocketDataProvider(&data1);
995
996 MockRead data2_reads[] = {
997 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
998 };
999 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1000 session_deps.socket_factory.AddSocketDataProvider(&data2);
1001
[email protected]0b0bf032010-09-21 18:08:501002 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1003 std::string response_lines[kNumUnreadBodies];
1004
1005 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:131006 TestCompletionCallback callback;
1007
1008 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1009
1010 int rv = trans->Start(&request, &callback, BoundNetLog());
1011 EXPECT_EQ(ERR_IO_PENDING, rv);
1012
1013 rv = callback.WaitForResult();
1014 EXPECT_EQ(OK, rv);
1015
1016 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501017 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131018
[email protected]0b0bf032010-09-21 18:08:501019 ASSERT_TRUE(response->headers != NULL);
1020 response_lines[i] = response->headers->GetStatusLine();
1021
1022 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131023 }
[email protected]0b0bf032010-09-21 18:08:501024
1025 const char* const kStatusLines[] = {
1026 "HTTP/1.1 204 No Content",
1027 "HTTP/1.1 205 Reset Content",
1028 "HTTP/1.1 304 Not Modified",
1029 "HTTP/1.1 302 Found",
1030 "HTTP/1.1 302 Found",
1031 "HTTP/1.1 301 Moved Permanently",
1032 "HTTP/1.1 301 Moved Permanently",
1033 };
1034
1035 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1036 forgot_to_update_kStatusLines);
1037
1038 for (int i = 0; i < kNumUnreadBodies; ++i)
1039 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1040
1041 TestCompletionCallback callback;
1042 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1043 int rv = trans->Start(&request, &callback, BoundNetLog());
1044 EXPECT_EQ(ERR_IO_PENDING, rv);
1045 rv = callback.WaitForResult();
1046 EXPECT_EQ(OK, rv);
1047 const HttpResponseInfo* response = trans->GetResponseInfo();
1048 ASSERT_TRUE(response != NULL);
1049 ASSERT_TRUE(response->headers != NULL);
1050 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1051 std::string response_data;
1052 rv = ReadTransaction(trans.get(), &response_data);
1053 EXPECT_EQ(OK, rv);
1054 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131055}
1056
[email protected]038e9a32008-10-08 22:40:161057// Test the request-challenge-retry sequence for basic auth.
1058// (basic auth is the easiest to mock, because it has no randomness).
1059TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421060 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161061 request.method = "GET";
1062 request.url = GURL("http://www.google.com/");
1063 request.load_flags = 0;
1064
[email protected]cb9bf6ca2011-01-28 13:15:271065 SessionDependencies session_deps;
1066 scoped_ptr<HttpTransaction> trans(
1067 new HttpNetworkTransaction(CreateSession(&session_deps)));
1068
[email protected]f9ee6b52008-11-08 06:46:231069 MockWrite data_writes1[] = {
1070 MockWrite("GET / HTTP/1.1\r\n"
1071 "Host: www.google.com\r\n"
1072 "Connection: keep-alive\r\n\r\n"),
1073 };
1074
[email protected]038e9a32008-10-08 22:40:161075 MockRead data_reads1[] = {
1076 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1077 // Give a couple authenticate options (only the middle one is actually
1078 // supported).
[email protected]22927ad2009-09-21 19:56:191079 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161080 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1081 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1082 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1083 // Large content-length -- won't matter, as connection will be reset.
1084 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421085 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161086 };
1087
1088 // After calling trans->RestartWithAuth(), this is the request we should
1089 // be issuing -- the final header line contains the credentials.
1090 MockWrite data_writes2[] = {
1091 MockWrite("GET / HTTP/1.1\r\n"
1092 "Host: www.google.com\r\n"
1093 "Connection: keep-alive\r\n"
1094 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1095 };
1096
1097 // Lastly, the server responds with the actual content.
1098 MockRead data_reads2[] = {
1099 MockRead("HTTP/1.0 200 OK\r\n"),
1100 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1101 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421102 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161103 };
1104
[email protected]31a2bfe2010-02-09 08:03:391105 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1106 data_writes1, arraysize(data_writes1));
1107 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1108 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591109 session_deps.socket_factory.AddSocketDataProvider(&data1);
1110 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161111
1112 TestCompletionCallback callback1;
1113
[email protected]5a1d7ca2010-04-28 20:12:271114 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421115 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161116
1117 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421118 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161119
[email protected]1c773ea12009-04-28 19:58:421120 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161121 EXPECT_FALSE(response == NULL);
1122
1123 // The password prompt info should have been set in response->auth_challenge.
1124 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1125
[email protected]71e4573a2009-05-21 22:03:001126 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161127 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1128 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1129
1130 TestCompletionCallback callback2;
1131
[email protected]13c8a092010-07-29 06:15:441132 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421133 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161134
1135 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421136 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161137
1138 response = trans->GetResponseInfo();
1139 EXPECT_FALSE(response == NULL);
1140 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1141 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161142}
1143
[email protected]861fcd52009-08-26 02:33:461144TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461145 HttpRequestInfo request;
1146 request.method = "GET";
1147 request.url = GURL("http://www.google.com/");
1148 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1149
[email protected]cb9bf6ca2011-01-28 13:15:271150 SessionDependencies session_deps;
1151 scoped_ptr<HttpTransaction> trans(
1152 new HttpNetworkTransaction(CreateSession(&session_deps)));
1153
[email protected]861fcd52009-08-26 02:33:461154 MockWrite data_writes[] = {
1155 MockWrite("GET / HTTP/1.1\r\n"
1156 "Host: www.google.com\r\n"
1157 "Connection: keep-alive\r\n\r\n"),
1158 };
1159
1160 MockRead data_reads[] = {
1161 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1162 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1163 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1164 // Large content-length -- won't matter, as connection will be reset.
1165 MockRead("Content-Length: 10000\r\n\r\n"),
1166 MockRead(false, ERR_FAILED),
1167 };
1168
[email protected]31a2bfe2010-02-09 08:03:391169 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1170 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591171 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461172 TestCompletionCallback callback;
1173
[email protected]5a1d7ca2010-04-28 20:12:271174 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461175 EXPECT_EQ(ERR_IO_PENDING, rv);
1176
1177 rv = callback.WaitForResult();
1178 EXPECT_EQ(0, rv);
1179
1180 const HttpResponseInfo* response = trans->GetResponseInfo();
1181 ASSERT_FALSE(response == NULL);
1182 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1183}
1184
[email protected]2d2697f92009-02-18 21:00:321185// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1186// connection.
1187TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421188 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321189 request.method = "GET";
1190 request.url = GURL("http://www.google.com/");
1191 request.load_flags = 0;
1192
[email protected]cb9bf6ca2011-01-28 13:15:271193 SessionDependencies session_deps;
1194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1195
[email protected]2d2697f92009-02-18 21:00:321196 MockWrite data_writes1[] = {
1197 MockWrite("GET / HTTP/1.1\r\n"
1198 "Host: www.google.com\r\n"
1199 "Connection: keep-alive\r\n\r\n"),
1200
1201 // After calling trans->RestartWithAuth(), this is the request we should
1202 // be issuing -- the final header line contains the credentials.
1203 MockWrite("GET / HTTP/1.1\r\n"
1204 "Host: www.google.com\r\n"
1205 "Connection: keep-alive\r\n"
1206 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1207 };
1208
1209 MockRead data_reads1[] = {
1210 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1211 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1212 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1213 MockRead("Content-Length: 14\r\n\r\n"),
1214 MockRead("Unauthorized\r\n"),
1215
1216 // Lastly, the server responds with the actual content.
1217 MockRead("HTTP/1.1 200 OK\r\n"),
1218 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501219 MockRead("Content-Length: 5\r\n\r\n"),
1220 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321221 };
1222
[email protected]2d0a4f92011-05-05 16:38:461223 // If there is a regression where we disconnect a Keep-Alive
1224 // connection during an auth roundtrip, we'll end up reading this.
1225 MockRead data_reads2[] = {
1226 MockRead(false, ERR_FAILED),
1227 };
1228
[email protected]31a2bfe2010-02-09 08:03:391229 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1230 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461231 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1232 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591233 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461234 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321235
1236 TestCompletionCallback callback1;
1237
[email protected]0b0bf032010-09-21 18:08:501238 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271239 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421240 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321241
1242 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421243 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321244
[email protected]1c773ea12009-04-28 19:58:421245 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321246 EXPECT_FALSE(response == NULL);
1247
1248 // The password prompt info should have been set in response->auth_challenge.
1249 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1250
[email protected]71e4573a2009-05-21 22:03:001251 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321252 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1253 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1254
1255 TestCompletionCallback callback2;
1256
[email protected]13c8a092010-07-29 06:15:441257 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421258 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321259
1260 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421261 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321262
1263 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461264 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321265 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501266 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321267}
1268
1269// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1270// connection and with no response body to drain.
1271TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421272 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321273 request.method = "GET";
1274 request.url = GURL("http://www.google.com/");
1275 request.load_flags = 0;
1276
[email protected]cb9bf6ca2011-01-28 13:15:271277 SessionDependencies session_deps;
1278 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1279
[email protected]2d2697f92009-02-18 21:00:321280 MockWrite data_writes1[] = {
1281 MockWrite("GET / HTTP/1.1\r\n"
1282 "Host: www.google.com\r\n"
1283 "Connection: keep-alive\r\n\r\n"),
1284
1285 // After calling trans->RestartWithAuth(), this is the request we should
1286 // be issuing -- the final header line contains the credentials.
1287 MockWrite("GET / HTTP/1.1\r\n"
1288 "Host: www.google.com\r\n"
1289 "Connection: keep-alive\r\n"
1290 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1291 };
1292
[email protected]2d2697f92009-02-18 21:00:321293 MockRead data_reads1[] = {
1294 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1295 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311296 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321297
1298 // Lastly, the server responds with the actual content.
1299 MockRead("HTTP/1.1 200 OK\r\n"),
1300 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501301 MockRead("Content-Length: 5\r\n\r\n"),
1302 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321303 };
1304
[email protected]2d0a4f92011-05-05 16:38:461305 // An incorrect reconnect would cause this to be read.
1306 MockRead data_reads2[] = {
1307 MockRead(false, ERR_FAILED),
1308 };
1309
[email protected]31a2bfe2010-02-09 08:03:391310 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1311 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461312 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1313 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591314 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461315 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321316
1317 TestCompletionCallback callback1;
1318
[email protected]0b0bf032010-09-21 18:08:501319 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271320 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421321 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321322
1323 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421324 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321325
[email protected]1c773ea12009-04-28 19:58:421326 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321327 EXPECT_FALSE(response == NULL);
1328
1329 // The password prompt info should have been set in response->auth_challenge.
1330 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1331
[email protected]71e4573a2009-05-21 22:03:001332 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321333 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1334 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1335
1336 TestCompletionCallback callback2;
1337
[email protected]13c8a092010-07-29 06:15:441338 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421339 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321340
1341 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421342 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321343
1344 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461345 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321346 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501347 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321348}
1349
1350// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1351// connection and with a large response body to drain.
1352TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421353 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321354 request.method = "GET";
1355 request.url = GURL("http://www.google.com/");
1356 request.load_flags = 0;
1357
[email protected]cb9bf6ca2011-01-28 13:15:271358 SessionDependencies session_deps;
1359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1360
[email protected]2d2697f92009-02-18 21:00:321361 MockWrite data_writes1[] = {
1362 MockWrite("GET / HTTP/1.1\r\n"
1363 "Host: www.google.com\r\n"
1364 "Connection: keep-alive\r\n\r\n"),
1365
1366 // After calling trans->RestartWithAuth(), this is the request we should
1367 // be issuing -- the final header line contains the credentials.
1368 MockWrite("GET / HTTP/1.1\r\n"
1369 "Host: www.google.com\r\n"
1370 "Connection: keep-alive\r\n"
1371 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1372 };
1373
1374 // Respond with 5 kb of response body.
1375 std::string large_body_string("Unauthorized");
1376 large_body_string.append(5 * 1024, ' ');
1377 large_body_string.append("\r\n");
1378
1379 MockRead data_reads1[] = {
1380 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1381 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1382 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1383 // 5134 = 12 + 5 * 1024 + 2
1384 MockRead("Content-Length: 5134\r\n\r\n"),
1385 MockRead(true, large_body_string.data(), large_body_string.size()),
1386
1387 // Lastly, the server responds with the actual content.
1388 MockRead("HTTP/1.1 200 OK\r\n"),
1389 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501390 MockRead("Content-Length: 5\r\n\r\n"),
1391 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321392 };
1393
[email protected]2d0a4f92011-05-05 16:38:461394 // An incorrect reconnect would cause this to be read.
1395 MockRead data_reads2[] = {
1396 MockRead(false, ERR_FAILED),
1397 };
1398
[email protected]31a2bfe2010-02-09 08:03:391399 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1400 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461401 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1402 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591403 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461404 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321405
1406 TestCompletionCallback callback1;
1407
[email protected]0b0bf032010-09-21 18:08:501408 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271409 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421410 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321411
1412 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421413 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321414
[email protected]1c773ea12009-04-28 19:58:421415 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321416 EXPECT_FALSE(response == NULL);
1417
1418 // The password prompt info should have been set in response->auth_challenge.
1419 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1420
[email protected]71e4573a2009-05-21 22:03:001421 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321422 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1423 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1424
1425 TestCompletionCallback callback2;
1426
[email protected]13c8a092010-07-29 06:15:441427 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421428 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321429
1430 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421431 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321432
1433 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461434 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321435 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501436 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321437}
1438
1439// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311440// connection, but the server gets impatient and closes the connection.
1441TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311442 HttpRequestInfo request;
1443 request.method = "GET";
1444 request.url = GURL("http://www.google.com/");
1445 request.load_flags = 0;
1446
[email protected]cb9bf6ca2011-01-28 13:15:271447 SessionDependencies session_deps;
1448 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1449
[email protected]11203f012009-11-12 23:02:311450 MockWrite data_writes1[] = {
1451 MockWrite("GET / HTTP/1.1\r\n"
1452 "Host: www.google.com\r\n"
1453 "Connection: keep-alive\r\n\r\n"),
1454 // This simulates the seemingly successful write to a closed connection
1455 // if the bug is not fixed.
1456 MockWrite("GET / HTTP/1.1\r\n"
1457 "Host: www.google.com\r\n"
1458 "Connection: keep-alive\r\n"
1459 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1460 };
1461
1462 MockRead data_reads1[] = {
1463 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1464 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1465 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1466 MockRead("Content-Length: 14\r\n\r\n"),
1467 // Tell MockTCPClientSocket to simulate the server closing the connection.
1468 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1469 MockRead("Unauthorized\r\n"),
1470 MockRead(false, OK), // The server closes the connection.
1471 };
1472
1473 // After calling trans->RestartWithAuth(), this is the request we should
1474 // be issuing -- the final header line contains the credentials.
1475 MockWrite data_writes2[] = {
1476 MockWrite("GET / HTTP/1.1\r\n"
1477 "Host: www.google.com\r\n"
1478 "Connection: keep-alive\r\n"
1479 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1480 };
1481
1482 // Lastly, the server responds with the actual content.
1483 MockRead data_reads2[] = {
1484 MockRead("HTTP/1.1 200 OK\r\n"),
1485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501486 MockRead("Content-Length: 5\r\n\r\n"),
1487 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311488 };
1489
[email protected]31a2bfe2010-02-09 08:03:391490 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1491 data_writes1, arraysize(data_writes1));
1492 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1493 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311494 session_deps.socket_factory.AddSocketDataProvider(&data1);
1495 session_deps.socket_factory.AddSocketDataProvider(&data2);
1496
1497 TestCompletionCallback callback1;
1498
[email protected]0b0bf032010-09-21 18:08:501499 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271500 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311501 EXPECT_EQ(ERR_IO_PENDING, rv);
1502
1503 rv = callback1.WaitForResult();
1504 EXPECT_EQ(OK, rv);
1505
1506 const HttpResponseInfo* response = trans->GetResponseInfo();
1507 EXPECT_FALSE(response == NULL);
1508
1509 // The password prompt info should have been set in response->auth_challenge.
1510 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1511
1512 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1513 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1514 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1515
1516 TestCompletionCallback callback2;
1517
[email protected]13c8a092010-07-29 06:15:441518 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311519 EXPECT_EQ(ERR_IO_PENDING, rv);
1520
1521 rv = callback2.WaitForResult();
1522 EXPECT_EQ(OK, rv);
1523
1524 response = trans->GetResponseInfo();
1525 ASSERT_FALSE(response == NULL);
1526 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501527 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311528}
1529
[email protected]394816e92010-08-03 07:38:591530// Test the request-challenge-retry sequence for basic auth, over a connection
1531// that requires a restart when setting up an SSL tunnel.
1532TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591533 HttpRequestInfo request;
1534 request.method = "GET";
1535 request.url = GURL("https://www.google.com/");
1536 // when the no authentication data flag is set.
1537 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1538
[email protected]cb9bf6ca2011-01-28 13:15:271539 // Configure against proxy server "myproxy:70".
1540 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1541 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1542 session_deps.net_log = log.bound().net_log();
1543 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1544
[email protected]394816e92010-08-03 07:38:591545 // Since we have proxy, should try to establish tunnel.
1546 MockWrite data_writes1[] = {
1547 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1548 "Host: www.google.com\r\n"
1549 "Proxy-Connection: keep-alive\r\n\r\n"),
1550
1551 // After calling trans->RestartWithAuth(), this is the request we should
1552 // be issuing -- the final header line contains the credentials.
1553 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1554 "Host: www.google.com\r\n"
1555 "Proxy-Connection: keep-alive\r\n"
1556 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1557
1558 MockWrite("GET / HTTP/1.1\r\n"
1559 "Host: www.google.com\r\n"
1560 "Connection: keep-alive\r\n\r\n"),
1561 };
1562
1563 // The proxy responds to the connect with a 407, using a persistent
1564 // connection.
1565 MockRead data_reads1[] = {
1566 // No credentials.
1567 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1568 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1569 MockRead("Proxy-Connection: close\r\n\r\n"),
1570
1571 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1572
1573 MockRead("HTTP/1.1 200 OK\r\n"),
1574 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501575 MockRead("Content-Length: 5\r\n\r\n"),
1576 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591577 };
1578
1579 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1580 data_writes1, arraysize(data_writes1));
1581 session_deps.socket_factory.AddSocketDataProvider(&data1);
1582 SSLSocketDataProvider ssl(true, OK);
1583 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1584
1585 TestCompletionCallback callback1;
1586
[email protected]0b0bf032010-09-21 18:08:501587 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1588
[email protected]394816e92010-08-03 07:38:591589 int rv = trans->Start(&request, &callback1, log.bound());
1590 EXPECT_EQ(ERR_IO_PENDING, rv);
1591
1592 rv = callback1.WaitForResult();
1593 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401594 net::CapturingNetLog::EntryList entries;
1595 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591596 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401597 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591598 NetLog::PHASE_NONE);
1599 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401600 entries, pos,
[email protected]394816e92010-08-03 07:38:591601 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1602 NetLog::PHASE_NONE);
1603
1604 const HttpResponseInfo* response = trans->GetResponseInfo();
1605 ASSERT_FALSE(response == NULL);
1606
1607 EXPECT_EQ(407, response->headers->response_code());
1608 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1609
1610 // The password prompt info should have been set in response->auth_challenge.
1611 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1612
1613 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1614 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1615 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1616
1617 TestCompletionCallback callback2;
1618
1619 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1620 EXPECT_EQ(ERR_IO_PENDING, rv);
1621
1622 rv = callback2.WaitForResult();
1623 EXPECT_EQ(OK, rv);
1624
1625 response = trans->GetResponseInfo();
1626 ASSERT_FALSE(response == NULL);
1627
1628 EXPECT_TRUE(response->headers->IsKeepAlive());
1629 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501630 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591631 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1632
1633 // The password prompt info should not be set.
1634 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501635
1636 trans.reset();
[email protected]102e27c2011-02-23 01:01:311637 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591638}
1639
[email protected]11203f012009-11-12 23:02:311640// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321641// proxy connection, when setting up an SSL tunnel.
1642TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271643 HttpRequestInfo request;
1644 request.method = "GET";
1645 request.url = GURL("https://www.google.com/");
1646 // Ensure that proxy authentication is attempted even
1647 // when the no authentication data flag is set.
1648 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1649
[email protected]2d2697f92009-02-18 21:00:321650 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001651 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541652 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1653 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591654 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321655
[email protected]5695b8c2009-09-30 21:36:431656 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321657
[email protected]2d2697f92009-02-18 21:00:321658 // Since we have proxy, should try to establish tunnel.
1659 MockWrite data_writes1[] = {
1660 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451661 "Host: www.google.com\r\n"
1662 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321663
1664 // After calling trans->RestartWithAuth(), this is the request we should
1665 // be issuing -- the final header line contains the credentials.
1666 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1667 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451668 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321669 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1670 };
1671
1672 // The proxy responds to the connect with a 407, using a persistent
1673 // connection.
1674 MockRead data_reads1[] = {
1675 // No credentials.
1676 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1677 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1678 MockRead("Content-Length: 10\r\n\r\n"),
1679 MockRead("0123456789"),
1680
1681 // Wrong credentials (wrong password).
1682 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1683 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1684 MockRead("Content-Length: 10\r\n\r\n"),
1685 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421686 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321687 };
1688
[email protected]31a2bfe2010-02-09 08:03:391689 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1690 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591691 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321692
1693 TestCompletionCallback callback1;
1694
[email protected]dbb83db2010-05-11 18:13:391695 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421696 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321697
1698 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421699 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401700 net::CapturingNetLog::EntryList entries;
1701 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391702 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401703 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391704 NetLog::PHASE_NONE);
1705 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401706 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391707 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1708 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321709
[email protected]1c773ea12009-04-28 19:58:421710 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321711 EXPECT_FALSE(response == NULL);
1712
1713 EXPECT_TRUE(response->headers->IsKeepAlive());
1714 EXPECT_EQ(407, response->headers->response_code());
1715 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421716 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321717
1718 // The password prompt info should have been set in response->auth_challenge.
1719 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1720
[email protected]71e4573a2009-05-21 22:03:001721 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321722 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1723 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1724
1725 TestCompletionCallback callback2;
1726
1727 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441728 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421729 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321730
1731 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421732 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321733
1734 response = trans->GetResponseInfo();
1735 EXPECT_FALSE(response == NULL);
1736
1737 EXPECT_TRUE(response->headers->IsKeepAlive());
1738 EXPECT_EQ(407, response->headers->response_code());
1739 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421740 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321741
1742 // The password prompt info should have been set in response->auth_challenge.
1743 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1744
[email protected]71e4573a2009-05-21 22:03:001745 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321746 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1747 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131748
[email protected]e60e47a2010-07-14 03:37:181749 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1750 // out of scope.
[email protected]102e27c2011-02-23 01:01:311751 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321752}
1753
[email protected]a8e9b162009-03-12 00:06:441754// Test that we don't read the response body when we fail to establish a tunnel,
1755// even if the user cancels the proxy's auth attempt.
1756TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271757 HttpRequestInfo request;
1758 request.method = "GET";
1759 request.url = GURL("https://www.google.com/");
1760 request.load_flags = 0;
1761
[email protected]a8e9b162009-03-12 00:06:441762 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001763 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441764
[email protected]e44de5d2009-06-05 20:12:451765 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441766
[email protected]5695b8c2009-09-30 21:36:431767 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441768
[email protected]a8e9b162009-03-12 00:06:441769 // Since we have proxy, should try to establish tunnel.
1770 MockWrite data_writes[] = {
1771 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451772 "Host: www.google.com\r\n"
1773 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441774 };
1775
1776 // The proxy responds to the connect with a 407.
1777 MockRead data_reads[] = {
1778 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1779 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1780 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421781 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441782 };
1783
[email protected]31a2bfe2010-02-09 08:03:391784 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1785 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591786 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441787
1788 TestCompletionCallback callback;
1789
[email protected]5a1d7ca2010-04-28 20:12:271790 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421791 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441792
1793 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421794 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441795
[email protected]1c773ea12009-04-28 19:58:421796 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441797 EXPECT_FALSE(response == NULL);
1798
1799 EXPECT_TRUE(response->headers->IsKeepAlive());
1800 EXPECT_EQ(407, response->headers->response_code());
1801 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421802 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441803
1804 std::string response_data;
1805 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421806 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181807
1808 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311809 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441810}
1811
[email protected]8fdbcd22010-05-05 02:54:521812// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1813// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1814TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521815 HttpRequestInfo request;
1816 request.method = "GET";
1817 request.url = GURL("http://www.google.com/");
1818 request.load_flags = 0;
1819
[email protected]cb9bf6ca2011-01-28 13:15:271820 // We are using a DIRECT connection (i.e. no proxy) for this session.
1821 SessionDependencies session_deps;
1822 scoped_ptr<HttpTransaction> trans(
1823 new HttpNetworkTransaction(CreateSession(&session_deps)));
1824
[email protected]8fdbcd22010-05-05 02:54:521825 MockWrite data_writes1[] = {
1826 MockWrite("GET / HTTP/1.1\r\n"
1827 "Host: www.google.com\r\n"
1828 "Connection: keep-alive\r\n\r\n"),
1829 };
1830
1831 MockRead data_reads1[] = {
1832 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1833 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1834 // Large content-length -- won't matter, as connection will be reset.
1835 MockRead("Content-Length: 10000\r\n\r\n"),
1836 MockRead(false, ERR_FAILED),
1837 };
1838
1839 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1840 data_writes1, arraysize(data_writes1));
1841 session_deps.socket_factory.AddSocketDataProvider(&data1);
1842
1843 TestCompletionCallback callback;
1844
1845 int rv = trans->Start(&request, &callback, BoundNetLog());
1846 EXPECT_EQ(ERR_IO_PENDING, rv);
1847
1848 rv = callback.WaitForResult();
1849 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1850}
1851
[email protected]7a67a8152010-11-05 18:31:101852// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1853// through a non-authenticating proxy. The request should fail with
1854// ERR_UNEXPECTED_PROXY_AUTH.
1855// Note that it is impossible to detect if an HTTP server returns a 407 through
1856// a non-authenticating proxy - there is nothing to indicate whether the
1857// response came from the proxy or the server, so it is treated as if the proxy
1858// issued the challenge.
1859TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271860 HttpRequestInfo request;
1861 request.method = "GET";
1862 request.url = GURL("https://www.google.com/");
1863
[email protected]7a67a8152010-11-05 18:31:101864 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1865 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1866 session_deps.net_log = log.bound().net_log();
1867 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1868
[email protected]7a67a8152010-11-05 18:31:101869 // Since we have proxy, should try to establish tunnel.
1870 MockWrite data_writes1[] = {
1871 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1872 "Host: www.google.com\r\n"
1873 "Proxy-Connection: keep-alive\r\n\r\n"),
1874
1875 MockWrite("GET / HTTP/1.1\r\n"
1876 "Host: www.google.com\r\n"
1877 "Connection: keep-alive\r\n\r\n"),
1878 };
1879
1880 MockRead data_reads1[] = {
1881 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1882
1883 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1884 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1885 MockRead("\r\n"),
1886 MockRead(false, OK),
1887 };
1888
1889 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1890 data_writes1, arraysize(data_writes1));
1891 session_deps.socket_factory.AddSocketDataProvider(&data1);
1892 SSLSocketDataProvider ssl(true, OK);
1893 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1894
1895 TestCompletionCallback callback1;
1896
1897 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1898
1899 int rv = trans->Start(&request, &callback1, log.bound());
1900 EXPECT_EQ(ERR_IO_PENDING, rv);
1901
1902 rv = callback1.WaitForResult();
1903 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401904 net::CapturingNetLog::EntryList entries;
1905 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101906 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401907 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101908 NetLog::PHASE_NONE);
1909 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401910 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101911 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1912 NetLog::PHASE_NONE);
1913}
[email protected]2df19bb2010-08-25 20:13:461914
1915// Test a simple get through an HTTPS Proxy.
1916TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271917 HttpRequestInfo request;
1918 request.method = "GET";
1919 request.url = GURL("http://www.google.com/");
1920
[email protected]2df19bb2010-08-25 20:13:461921 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001922 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461923 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1924 session_deps.net_log = log.bound().net_log();
1925 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1926
[email protected]2df19bb2010-08-25 20:13:461927 // Since we have proxy, should use full url
1928 MockWrite data_writes1[] = {
1929 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1930 "Host: www.google.com\r\n"
1931 "Proxy-Connection: keep-alive\r\n\r\n"),
1932 };
1933
1934 MockRead data_reads1[] = {
1935 MockRead("HTTP/1.1 200 OK\r\n"),
1936 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1937 MockRead("Content-Length: 100\r\n\r\n"),
1938 MockRead(false, OK),
1939 };
1940
1941 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1942 data_writes1, arraysize(data_writes1));
1943 session_deps.socket_factory.AddSocketDataProvider(&data1);
1944 SSLSocketDataProvider ssl(true, OK);
1945 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1946
1947 TestCompletionCallback callback1;
1948
[email protected]0b0bf032010-09-21 18:08:501949 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1950
[email protected]2df19bb2010-08-25 20:13:461951 int rv = trans->Start(&request, &callback1, log.bound());
1952 EXPECT_EQ(ERR_IO_PENDING, rv);
1953
1954 rv = callback1.WaitForResult();
1955 EXPECT_EQ(OK, rv);
1956
1957 const HttpResponseInfo* response = trans->GetResponseInfo();
1958 ASSERT_FALSE(response == NULL);
1959
1960 EXPECT_TRUE(response->headers->IsKeepAlive());
1961 EXPECT_EQ(200, response->headers->response_code());
1962 EXPECT_EQ(100, response->headers->GetContentLength());
1963 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1964
1965 // The password prompt info should not be set.
1966 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1967}
1968
[email protected]7642b5ae2010-09-01 20:55:171969// Test a SPDY get through an HTTPS Proxy.
1970TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271971 HttpRequestInfo request;
1972 request.method = "GET";
1973 request.url = GURL("http://www.google.com/");
1974 request.load_flags = 0;
1975
[email protected]7642b5ae2010-09-01 20:55:171976 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001977 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171978 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1979 session_deps.net_log = log.bound().net_log();
1980 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1981
[email protected]7642b5ae2010-09-01 20:55:171982 // fetch http://www.google.com/ via SPDY
1983 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1984 false));
1985 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1986
1987 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1988 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1989 MockRead spdy_reads[] = {
1990 CreateMockRead(*resp),
1991 CreateMockRead(*data),
1992 MockRead(true, 0, 0),
1993 };
1994
1995 scoped_refptr<DelayedSocketData> spdy_data(
1996 new DelayedSocketData(
1997 1, // wait for one write to finish before reading.
1998 spdy_reads, arraysize(spdy_reads),
1999 spdy_writes, arraysize(spdy_writes)));
2000 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2001
2002 SSLSocketDataProvider ssl(true, OK);
2003 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2004 ssl.next_proto = "spdy/2";
2005 ssl.was_npn_negotiated = true;
2006 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2007
2008 TestCompletionCallback callback1;
2009
[email protected]0b0bf032010-09-21 18:08:502010 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2011
[email protected]7642b5ae2010-09-01 20:55:172012 int rv = trans->Start(&request, &callback1, log.bound());
2013 EXPECT_EQ(ERR_IO_PENDING, rv);
2014
2015 rv = callback1.WaitForResult();
2016 EXPECT_EQ(OK, rv);
2017
2018 const HttpResponseInfo* response = trans->GetResponseInfo();
2019 ASSERT_TRUE(response != NULL);
2020 ASSERT_TRUE(response->headers != NULL);
2021 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2022
2023 std::string response_data;
2024 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2025 EXPECT_EQ(net::kUploadData, response_data);
2026}
2027
[email protected]dc7bd1c52010-11-12 00:01:132028// Test a SPDY get through an HTTPS Proxy.
2029TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272030 HttpRequestInfo request;
2031 request.method = "GET";
2032 request.url = GURL("http://www.google.com/");
2033 request.load_flags = 0;
2034
[email protected]dc7bd1c52010-11-12 00:01:132035 // Configure against https proxy server "proxy:70".
2036 SessionDependencies session_deps(
2037 ProxyService::CreateFixed("https://proxy:70"));
2038 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2039 session_deps.net_log = log.bound().net_log();
2040 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2041
[email protected]dc7bd1c52010-11-12 00:01:132042 // The first request will be a bare GET, the second request will be a
2043 // GET with a Proxy-Authorization header.
2044 scoped_ptr<spdy::SpdyFrame> req_get(
2045 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2046 const char* const kExtraAuthorizationHeaders[] = {
2047 "proxy-authorization",
2048 "Basic Zm9vOmJhcg==",
2049 };
2050 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2051 ConstructSpdyGet(
2052 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2053 false, 3, LOWEST, false));
2054 MockWrite spdy_writes[] = {
2055 CreateMockWrite(*req_get, 1),
2056 CreateMockWrite(*req_get_authorization, 4),
2057 };
2058
2059 // The first response is a 407 proxy authentication challenge, and the second
2060 // response will be a 200 response since the second request includes a valid
2061 // Authorization header.
2062 const char* const kExtraAuthenticationHeaders[] = {
2063 "Proxy-Authenticate",
2064 "Basic realm=\"MyRealm1\""
2065 };
2066 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2067 ConstructSpdySynReplyError(
2068 "407 Proxy Authentication Required",
2069 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2070 1));
2071 scoped_ptr<spdy::SpdyFrame> body_authentication(
2072 ConstructSpdyBodyFrame(1, true));
2073 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2074 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2075 MockRead spdy_reads[] = {
2076 CreateMockRead(*resp_authentication, 2),
2077 CreateMockRead(*body_authentication, 3),
2078 CreateMockRead(*resp_data, 5),
2079 CreateMockRead(*body_data, 6),
2080 MockRead(true, 0, 7),
2081 };
2082
2083 scoped_refptr<OrderedSocketData> data(
2084 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2085 spdy_writes, arraysize(spdy_writes)));
2086 session_deps.socket_factory.AddSocketDataProvider(data);
2087
2088 SSLSocketDataProvider ssl(true, OK);
2089 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2090 ssl.next_proto = "spdy/2";
2091 ssl.was_npn_negotiated = true;
2092 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2093
2094 TestCompletionCallback callback1;
2095
2096 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2097
2098 int rv = trans->Start(&request, &callback1, log.bound());
2099 EXPECT_EQ(ERR_IO_PENDING, rv);
2100
2101 rv = callback1.WaitForResult();
2102 EXPECT_EQ(OK, rv);
2103
2104 const HttpResponseInfo* const response = trans->GetResponseInfo();
2105
2106 ASSERT_TRUE(response != NULL);
2107 ASSERT_TRUE(response->headers != NULL);
2108 EXPECT_EQ(407, response->headers->response_code());
2109 EXPECT_TRUE(response->was_fetched_via_spdy);
2110
2111 // The password prompt info should have been set in response->auth_challenge.
2112 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2113 EXPECT_TRUE(response->auth_challenge->is_proxy);
2114 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2115 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2116 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2117
2118 TestCompletionCallback callback2;
2119
2120 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2121 EXPECT_EQ(ERR_IO_PENDING, rv);
2122
2123 rv = callback2.WaitForResult();
2124 EXPECT_EQ(OK, rv);
2125
2126 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2127
2128 ASSERT_TRUE(response_restart != NULL);
2129 ASSERT_TRUE(response_restart->headers != NULL);
2130 EXPECT_EQ(200, response_restart->headers->response_code());
2131 // The password prompt info should not be set.
2132 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2133}
2134
[email protected]d9da5fe2010-10-13 22:37:162135// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2136TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272137 HttpRequestInfo request;
2138 request.method = "GET";
2139 request.url = GURL("https://www.google.com/");
2140 request.load_flags = 0;
2141
[email protected]d9da5fe2010-10-13 22:37:162142 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002143 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162144 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2145 session_deps.net_log = log.bound().net_log();
2146 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2147
2148 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2149
[email protected]d9da5fe2010-10-13 22:37:162150 // CONNECT to www.google.com:443 via SPDY
2151 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2152 // fetch https://www.google.com/ via HTTP
2153
2154 const char get[] = "GET / HTTP/1.1\r\n"
2155 "Host: www.google.com\r\n"
2156 "Connection: keep-alive\r\n\r\n";
2157 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2158 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2159 MockWrite spdy_writes[] = {
2160 CreateMockWrite(*connect, 1),
2161 CreateMockWrite(*wrapped_get, 3)
2162 };
2163
2164 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2165 const char resp[] = "HTTP/1.1 200 OK\r\n"
2166 "Content-Length: 10\r\n\r\n";
2167
2168 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2169 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2170 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2171 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2172 MockRead spdy_reads[] = {
2173 CreateMockRead(*conn_resp, 2, true),
2174 CreateMockRead(*wrapped_get_resp, 4, true),
2175 CreateMockRead(*wrapped_body, 5, true),
2176 CreateMockRead(*wrapped_body, 6, true),
2177 MockRead(true, 0, 7),
2178 };
2179
2180 scoped_refptr<OrderedSocketData> spdy_data(
2181 new OrderedSocketData(
2182 spdy_reads, arraysize(spdy_reads),
2183 spdy_writes, arraysize(spdy_writes)));
2184 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2185
2186 SSLSocketDataProvider ssl(true, OK);
2187 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2188 ssl.next_proto = "spdy/2";
2189 ssl.was_npn_negotiated = true;
2190 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2191 SSLSocketDataProvider ssl2(true, OK);
2192 ssl2.was_npn_negotiated = false;
2193 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2194
2195 TestCompletionCallback callback1;
2196
2197 int rv = trans->Start(&request, &callback1, log.bound());
2198 EXPECT_EQ(ERR_IO_PENDING, rv);
2199
2200 rv = callback1.WaitForResult();
2201 EXPECT_EQ(OK, rv);
2202
2203 const HttpResponseInfo* response = trans->GetResponseInfo();
2204 ASSERT_TRUE(response != NULL);
2205 ASSERT_TRUE(response->headers != NULL);
2206 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2207
2208 std::string response_data;
2209 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2210 EXPECT_EQ("1234567890", response_data);
2211}
2212
2213// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2214TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272215 HttpRequestInfo request;
2216 request.method = "GET";
2217 request.url = GURL("https://www.google.com/");
2218 request.load_flags = 0;
2219
[email protected]d9da5fe2010-10-13 22:37:162220 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002221 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162222 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2223 session_deps.net_log = log.bound().net_log();
2224 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2225
2226 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2227
[email protected]d9da5fe2010-10-13 22:37:162228 // CONNECT to www.google.com:443 via SPDY
2229 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2230 // fetch https://www.google.com/ via SPDY
2231 const char* const kMyUrl = "https://www.google.com/";
2232 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2233 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2234 MockWrite spdy_writes[] = {
2235 CreateMockWrite(*connect, 1),
2236 CreateMockWrite(*wrapped_get, 3)
2237 };
2238
2239 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2240 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2241 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2242 ConstructWrappedSpdyFrame(get_resp, 1));
2243 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2244 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2245 MockRead spdy_reads[] = {
2246 CreateMockRead(*conn_resp, 2, true),
2247 CreateMockRead(*wrapped_get_resp, 4, true),
2248 CreateMockRead(*wrapped_body, 5, true),
2249 MockRead(true, 0, 1),
2250 };
2251
2252 scoped_refptr<OrderedSocketData> spdy_data(
2253 new OrderedSocketData(
2254 spdy_reads, arraysize(spdy_reads),
2255 spdy_writes, arraysize(spdy_writes)));
2256 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2257
2258 SSLSocketDataProvider ssl(true, OK);
2259 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2260 ssl.next_proto = "spdy/2";
2261 ssl.was_npn_negotiated = true;
2262 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2263 SSLSocketDataProvider ssl2(true, OK);
2264 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2265 ssl2.next_proto = "spdy/2";
2266 ssl2.was_npn_negotiated = true;
2267 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2268
2269 TestCompletionCallback callback1;
2270
2271 int rv = trans->Start(&request, &callback1, log.bound());
2272 EXPECT_EQ(ERR_IO_PENDING, rv);
2273
2274 rv = callback1.WaitForResult();
2275 EXPECT_EQ(OK, rv);
2276
2277 const HttpResponseInfo* response = trans->GetResponseInfo();
2278 ASSERT_TRUE(response != NULL);
2279 ASSERT_TRUE(response->headers != NULL);
2280 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2281
2282 std::string response_data;
2283 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2284 EXPECT_EQ(net::kUploadData, response_data);
2285}
2286
2287// Test a SPDY CONNECT failure through an HTTPS Proxy.
2288TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272289 HttpRequestInfo request;
2290 request.method = "GET";
2291 request.url = GURL("https://www.google.com/");
2292 request.load_flags = 0;
2293
[email protected]d9da5fe2010-10-13 22:37:162294 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002295 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162296 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2297 session_deps.net_log = log.bound().net_log();
2298 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2299
2300 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2301
[email protected]d9da5fe2010-10-13 22:37:162302 // CONNECT to www.google.com:443 via SPDY
2303 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2304 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2305
2306 MockWrite spdy_writes[] = {
2307 CreateMockWrite(*connect, 1),
2308 CreateMockWrite(*get, 3),
2309 };
2310
2311 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2312 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2313 MockRead spdy_reads[] = {
2314 CreateMockRead(*resp, 2, true),
2315 MockRead(true, 0, 4),
2316 };
2317
2318 scoped_refptr<OrderedSocketData> spdy_data(
2319 new OrderedSocketData(
2320 spdy_reads, arraysize(spdy_reads),
2321 spdy_writes, arraysize(spdy_writes)));
2322 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2323
2324 SSLSocketDataProvider ssl(true, OK);
2325 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2326 ssl.next_proto = "spdy/2";
2327 ssl.was_npn_negotiated = true;
2328 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2329 SSLSocketDataProvider ssl2(true, OK);
2330 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2331 ssl2.next_proto = "spdy/2";
2332 ssl2.was_npn_negotiated = true;
2333 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2334
2335 TestCompletionCallback callback1;
2336
2337 int rv = trans->Start(&request, &callback1, log.bound());
2338 EXPECT_EQ(ERR_IO_PENDING, rv);
2339
2340 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292341 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162342
2343 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292344 ASSERT_FALSE(response == NULL);
2345 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162346}
2347
[email protected]2df19bb2010-08-25 20:13:462348// Test the challenge-response-retry sequence through an HTTPS Proxy
2349TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462350 HttpRequestInfo request;
2351 request.method = "GET";
2352 request.url = GURL("http://www.google.com/");
2353 // when the no authentication data flag is set.
2354 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2355
[email protected]cb9bf6ca2011-01-28 13:15:272356 // Configure against https proxy server "proxy:70".
2357 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
2358 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2359 session_deps.net_log = log.bound().net_log();
2360 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2361
[email protected]2df19bb2010-08-25 20:13:462362 // Since we have proxy, should use full url
2363 MockWrite data_writes1[] = {
2364 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2365 "Host: www.google.com\r\n"
2366 "Proxy-Connection: keep-alive\r\n\r\n"),
2367
2368 // After calling trans->RestartWithAuth(), this is the request we should
2369 // be issuing -- the final header line contains the credentials.
2370 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2371 "Host: www.google.com\r\n"
2372 "Proxy-Connection: keep-alive\r\n"
2373 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2374 };
2375
2376 // The proxy responds to the GET with a 407, using a persistent
2377 // connection.
2378 MockRead data_reads1[] = {
2379 // No credentials.
2380 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2381 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2382 MockRead("Proxy-Connection: keep-alive\r\n"),
2383 MockRead("Content-Length: 0\r\n\r\n"),
2384
2385 MockRead("HTTP/1.1 200 OK\r\n"),
2386 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2387 MockRead("Content-Length: 100\r\n\r\n"),
2388 MockRead(false, OK),
2389 };
2390
2391 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2392 data_writes1, arraysize(data_writes1));
2393 session_deps.socket_factory.AddSocketDataProvider(&data1);
2394 SSLSocketDataProvider ssl(true, OK);
2395 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2396
2397 TestCompletionCallback callback1;
2398
[email protected]0b0bf032010-09-21 18:08:502399 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2400
[email protected]2df19bb2010-08-25 20:13:462401 int rv = trans->Start(&request, &callback1, log.bound());
2402 EXPECT_EQ(ERR_IO_PENDING, rv);
2403
2404 rv = callback1.WaitForResult();
2405 EXPECT_EQ(OK, rv);
2406
2407 const HttpResponseInfo* response = trans->GetResponseInfo();
2408 ASSERT_FALSE(response == NULL);
2409
2410 EXPECT_EQ(407, response->headers->response_code());
2411 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2412
2413 // The password prompt info should have been set in response->auth_challenge.
2414 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2415
2416 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2417 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2418 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2419
2420 TestCompletionCallback callback2;
2421
2422 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2423 EXPECT_EQ(ERR_IO_PENDING, rv);
2424
2425 rv = callback2.WaitForResult();
2426 EXPECT_EQ(OK, rv);
2427
2428 response = trans->GetResponseInfo();
2429 ASSERT_FALSE(response == NULL);
2430
2431 EXPECT_TRUE(response->headers->IsKeepAlive());
2432 EXPECT_EQ(200, response->headers->response_code());
2433 EXPECT_EQ(100, response->headers->GetContentLength());
2434 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2435
2436 // The password prompt info should not be set.
2437 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2438}
2439
[email protected]ff007e162009-05-23 09:13:152440void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082441 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422442 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082443 request.method = "GET";
2444 request.url = GURL("https://www.google.com/");
2445 request.load_flags = 0;
2446
[email protected]cb9bf6ca2011-01-28 13:15:272447 // Configure against proxy server "myproxy:70".
2448 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2449
2450 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2451
[email protected]c744cf22009-02-27 07:28:082452 // Since we have proxy, should try to establish tunnel.
2453 MockWrite data_writes[] = {
2454 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452455 "Host: www.google.com\r\n"
2456 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082457 };
2458
2459 MockRead data_reads[] = {
2460 status,
2461 MockRead("Content-Length: 10\r\n\r\n"),
2462 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422463 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082464 };
2465
[email protected]31a2bfe2010-02-09 08:03:392466 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2467 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592468 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082469
2470 TestCompletionCallback callback;
2471
[email protected]0b0bf032010-09-21 18:08:502472 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2473
[email protected]5a1d7ca2010-04-28 20:12:272474 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422475 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082476
2477 rv = callback.WaitForResult();
2478 EXPECT_EQ(expected_status, rv);
2479}
2480
[email protected]ff007e162009-05-23 09:13:152481void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082482 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422483 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082484}
2485
2486TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2487 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2488}
2489
2490TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2491 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2492}
2493
2494TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2495 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2496}
2497
2498TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2499 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2500}
2501
2502TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2503 ConnectStatusHelper(
2504 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2505}
2506
2507TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2508 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2509}
2510
2511TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2512 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2513}
2514
2515TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2516 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2517}
2518
2519TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2520 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2521}
2522
2523TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2524 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2525}
2526
2527TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2528 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2529}
2530
2531TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2532 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2533}
2534
2535TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2536 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2537}
2538
2539TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2540 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2541}
2542
2543TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2544 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2545}
2546
2547TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2548 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2549}
2550
2551TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2552 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2553}
2554
2555TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2556 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2557}
2558
2559TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2560 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2561}
2562
2563TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2564 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2565}
2566
2567TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2568 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2569}
2570
2571TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2572 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2573}
2574
2575TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2576 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2577}
2578
2579TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2580 ConnectStatusHelperWithExpectedStatus(
2581 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542582 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082583}
2584
2585TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2586 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2587}
2588
2589TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2590 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2591}
2592
2593TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2594 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2595}
2596
2597TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2598 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2599}
2600
2601TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2602 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2603}
2604
2605TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2606 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2607}
2608
2609TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2610 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2611}
2612
2613TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2614 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2615}
2616
2617TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2618 ConnectStatusHelper(
2619 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2620}
2621
2622TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2623 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2624}
2625
2626TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2627 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2628}
2629
2630TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2631 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2632}
2633
2634TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2635 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2636}
2637
2638TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2639 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2640}
2641
2642TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2643 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2644}
2645
2646TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2647 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2648}
2649
[email protected]038e9a32008-10-08 22:40:162650// Test the flow when both the proxy server AND origin server require
2651// authentication. Again, this uses basic auth for both since that is
2652// the simplest to mock.
2653TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272654 HttpRequestInfo request;
2655 request.method = "GET";
2656 request.url = GURL("http://www.google.com/");
2657 request.load_flags = 0;
2658
[email protected]81cdfcd2010-10-16 00:49:002659 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012660
[email protected]038e9a32008-10-08 22:40:162661 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422662 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432663 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162664
[email protected]f9ee6b52008-11-08 06:46:232665 MockWrite data_writes1[] = {
2666 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2667 "Host: www.google.com\r\n"
2668 "Proxy-Connection: keep-alive\r\n\r\n"),
2669 };
2670
[email protected]038e9a32008-10-08 22:40:162671 MockRead data_reads1[] = {
2672 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2673 // Give a couple authenticate options (only the middle one is actually
2674 // supported).
[email protected]22927ad2009-09-21 19:56:192675 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162676 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2677 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2678 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2679 // Large content-length -- won't matter, as connection will be reset.
2680 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422681 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162682 };
2683
2684 // After calling trans->RestartWithAuth() the first time, this is the
2685 // request we should be issuing -- the final header line contains the
2686 // proxy's credentials.
2687 MockWrite data_writes2[] = {
2688 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2689 "Host: www.google.com\r\n"
2690 "Proxy-Connection: keep-alive\r\n"
2691 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2692 };
2693
2694 // Now the proxy server lets the request pass through to origin server.
2695 // The origin server responds with a 401.
2696 MockRead data_reads2[] = {
2697 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2698 // Note: We are using the same realm-name as the proxy server. This is
2699 // completely valid, as realms are unique across hosts.
2700 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2701 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2702 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422703 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162704 };
2705
2706 // After calling trans->RestartWithAuth() the second time, we should send
2707 // the credentials for both the proxy and origin server.
2708 MockWrite data_writes3[] = {
2709 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2710 "Host: www.google.com\r\n"
2711 "Proxy-Connection: keep-alive\r\n"
2712 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2713 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2714 };
2715
2716 // Lastly we get the desired content.
2717 MockRead data_reads3[] = {
2718 MockRead("HTTP/1.0 200 OK\r\n"),
2719 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2720 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422721 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162722 };
2723
[email protected]31a2bfe2010-02-09 08:03:392724 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2725 data_writes1, arraysize(data_writes1));
2726 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2727 data_writes2, arraysize(data_writes2));
2728 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2729 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592730 session_deps.socket_factory.AddSocketDataProvider(&data1);
2731 session_deps.socket_factory.AddSocketDataProvider(&data2);
2732 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162733
2734 TestCompletionCallback callback1;
2735
[email protected]5a1d7ca2010-04-28 20:12:272736 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422737 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162738
2739 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422740 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162741
[email protected]1c773ea12009-04-28 19:58:422742 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162743 EXPECT_FALSE(response == NULL);
2744
2745 // The password prompt info should have been set in response->auth_challenge.
2746 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2747
[email protected]71e4573a2009-05-21 22:03:002748 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162749 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2750 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2751
2752 TestCompletionCallback callback2;
2753
[email protected]13c8a092010-07-29 06:15:442754 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422755 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162756
2757 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422758 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162759
2760 response = trans->GetResponseInfo();
2761 EXPECT_FALSE(response == NULL);
2762 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2763
[email protected]71e4573a2009-05-21 22:03:002764 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162765 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2766 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2767
2768 TestCompletionCallback callback3;
2769
[email protected]13c8a092010-07-29 06:15:442770 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422771 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162772
2773 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422774 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162775
2776 response = trans->GetResponseInfo();
2777 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2778 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162779}
[email protected]4ddaf2502008-10-23 18:26:192780
[email protected]ea9dc9a2009-09-05 00:43:322781// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2782// can't hook into its internals to cause it to generate predictable NTLM
2783// authorization headers.
2784#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292785// The NTLM authentication unit tests were generated by capturing the HTTP
2786// requests and responses using Fiddler 2 and inspecting the generated random
2787// bytes in the debugger.
2788
2789// Enter the correct password and authenticate successfully.
2790TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422791 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242792 request.method = "GET";
2793 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2794 request.load_flags = 0;
2795
[email protected]cb9bf6ca2011-01-28 13:15:272796 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2797 MockGetHostName);
2798 SessionDependencies session_deps;
2799 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2800
[email protected]3f918782009-02-28 01:29:242801 MockWrite data_writes1[] = {
2802 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2803 "Host: 172.22.68.17\r\n"
2804 "Connection: keep-alive\r\n\r\n"),
2805 };
2806
2807 MockRead data_reads1[] = {
2808 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042809 // Negotiate and NTLM are often requested together. However, we only want
2810 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2811 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242812 MockRead("WWW-Authenticate: NTLM\r\n"),
2813 MockRead("Connection: close\r\n"),
2814 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362815 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242816 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422817 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242818 };
2819
2820 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222821 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242822 // request we should be issuing -- the final header line contains a Type
2823 // 1 message.
2824 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2825 "Host: 172.22.68.17\r\n"
2826 "Connection: keep-alive\r\n"
2827 "Authorization: NTLM "
2828 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2829
2830 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2831 // (the credentials for the origin server). The second request continues
2832 // on the same connection.
2833 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2834 "Host: 172.22.68.17\r\n"
2835 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292836 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2837 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2838 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2839 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2840 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242841 };
2842
2843 MockRead data_reads2[] = {
2844 // The origin server responds with a Type 2 message.
2845 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2846 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292847 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242848 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2849 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2850 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2851 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2852 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2853 "BtAAAAAAA=\r\n"),
2854 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362855 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242856 MockRead("You are not authorized to view this page\r\n"),
2857
2858 // Lastly we get the desired content.
2859 MockRead("HTTP/1.1 200 OK\r\n"),
2860 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2861 MockRead("Content-Length: 13\r\n\r\n"),
2862 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422863 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242864 };
2865
[email protected]31a2bfe2010-02-09 08:03:392866 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2867 data_writes1, arraysize(data_writes1));
2868 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2869 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592870 session_deps.socket_factory.AddSocketDataProvider(&data1);
2871 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242872
2873 TestCompletionCallback callback1;
2874
[email protected]0b0bf032010-09-21 18:08:502875 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2876
[email protected]5a1d7ca2010-04-28 20:12:272877 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422878 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242879
2880 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422881 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242882
[email protected]0757e7702009-03-27 04:00:222883 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2884
[email protected]1c773ea12009-04-28 19:58:422885 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:252886 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:242887
[email protected]aef04272010-06-28 18:03:042888 // The password prompt info should have been set in
2889 // response->auth_challenge.
[email protected]10af5fe72011-01-31 16:17:252890 ASSERT_FALSE(response->auth_challenge.get() == NULL);
[email protected]3f918782009-02-28 01:29:242891
[email protected]71e4573a2009-05-21 22:03:002892 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242893 EXPECT_EQ(L"", response->auth_challenge->realm);
2894 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2895
[email protected]10af5fe72011-01-31 16:17:252896 TestCompletionCallback callback2;
2897
2898 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
2899 EXPECT_EQ(ERR_IO_PENDING, rv);
2900
2901 rv = callback2.WaitForResult();
2902 EXPECT_EQ(OK, rv);
2903
2904 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2905
2906 response = trans->GetResponseInfo();
2907 ASSERT_TRUE(response != NULL);
2908
2909 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2910
[email protected]0757e7702009-03-27 04:00:222911 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242912
[email protected]10af5fe72011-01-31 16:17:252913 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:422914 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242915
[email protected]0757e7702009-03-27 04:00:222916 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422917 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242918
2919 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042920 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242921 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2922 EXPECT_EQ(13, response->headers->GetContentLength());
2923}
2924
[email protected]385a4672009-03-11 22:21:292925// Enter a wrong password, and then the correct one.
2926TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422927 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292928 request.method = "GET";
2929 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2930 request.load_flags = 0;
2931
[email protected]cb9bf6ca2011-01-28 13:15:272932 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
2933 MockGetHostName);
2934 SessionDependencies session_deps;
2935 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2936
[email protected]385a4672009-03-11 22:21:292937 MockWrite data_writes1[] = {
2938 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2939 "Host: 172.22.68.17\r\n"
2940 "Connection: keep-alive\r\n\r\n"),
2941 };
2942
2943 MockRead data_reads1[] = {
2944 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042945 // Negotiate and NTLM are often requested together. However, we only want
2946 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2947 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292948 MockRead("WWW-Authenticate: NTLM\r\n"),
2949 MockRead("Connection: close\r\n"),
2950 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362951 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292952 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422953 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292954 };
2955
2956 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222957 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292958 // request we should be issuing -- the final header line contains a Type
2959 // 1 message.
2960 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2961 "Host: 172.22.68.17\r\n"
2962 "Connection: keep-alive\r\n"
2963 "Authorization: NTLM "
2964 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2965
2966 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2967 // (the credentials for the origin server). The second request continues
2968 // on the same connection.
2969 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2970 "Host: 172.22.68.17\r\n"
2971 "Connection: keep-alive\r\n"
2972 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2973 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2974 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2975 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2976 "4Ww7b7E=\r\n\r\n"),
2977 };
2978
2979 MockRead data_reads2[] = {
2980 // The origin server responds with a Type 2 message.
2981 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2982 MockRead("WWW-Authenticate: NTLM "
2983 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2984 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2985 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2986 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2987 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2988 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2989 "BtAAAAAAA=\r\n"),
2990 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362991 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292992 MockRead("You are not authorized to view this page\r\n"),
2993
2994 // Wrong password.
2995 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292996 MockRead("WWW-Authenticate: NTLM\r\n"),
2997 MockRead("Connection: close\r\n"),
2998 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362999 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293000 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423001 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293002 };
3003
3004 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223005 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293006 // request we should be issuing -- the final header line contains a Type
3007 // 1 message.
3008 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3009 "Host: 172.22.68.17\r\n"
3010 "Connection: keep-alive\r\n"
3011 "Authorization: NTLM "
3012 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3013
3014 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3015 // (the credentials for the origin server). The second request continues
3016 // on the same connection.
3017 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3018 "Host: 172.22.68.17\r\n"
3019 "Connection: keep-alive\r\n"
3020 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3021 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3022 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3023 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3024 "+4MUm7c=\r\n\r\n"),
3025 };
3026
3027 MockRead data_reads3[] = {
3028 // The origin server responds with a Type 2 message.
3029 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3030 MockRead("WWW-Authenticate: NTLM "
3031 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3032 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3033 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3034 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3035 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3036 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3037 "BtAAAAAAA=\r\n"),
3038 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363039 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293040 MockRead("You are not authorized to view this page\r\n"),
3041
3042 // Lastly we get the desired content.
3043 MockRead("HTTP/1.1 200 OK\r\n"),
3044 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3045 MockRead("Content-Length: 13\r\n\r\n"),
3046 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423047 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293048 };
3049
[email protected]31a2bfe2010-02-09 08:03:393050 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3051 data_writes1, arraysize(data_writes1));
3052 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3053 data_writes2, arraysize(data_writes2));
3054 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3055 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593056 session_deps.socket_factory.AddSocketDataProvider(&data1);
3057 session_deps.socket_factory.AddSocketDataProvider(&data2);
3058 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293059
3060 TestCompletionCallback callback1;
3061
[email protected]0b0bf032010-09-21 18:08:503062 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3063
[email protected]5a1d7ca2010-04-28 20:12:273064 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423065 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293066
3067 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423068 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293069
[email protected]0757e7702009-03-27 04:00:223070 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293071
[email protected]1c773ea12009-04-28 19:58:423072 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293073 EXPECT_FALSE(response == NULL);
3074
3075 // The password prompt info should have been set in response->auth_challenge.
3076 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3077
[email protected]71e4573a2009-05-21 22:03:003078 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293079 EXPECT_EQ(L"", response->auth_challenge->realm);
3080 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3081
[email protected]10af5fe72011-01-31 16:17:253082 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293083
[email protected]0757e7702009-03-27 04:00:223084 // Enter the wrong password.
[email protected]10af5fe72011-01-31 16:17:253085 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
[email protected]1c773ea12009-04-28 19:58:423086 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293087
[email protected]10af5fe72011-01-31 16:17:253088 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423089 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293090
[email protected]0757e7702009-03-27 04:00:223091 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:253092 TestCompletionCallback callback3;
3093 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423094 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253095 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423096 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223097 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3098
3099 response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:253100 ASSERT_TRUE(response != NULL);
[email protected]0757e7702009-03-27 04:00:223101
3102 // The password prompt info should have been set in response->auth_challenge.
3103 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3104
[email protected]71e4573a2009-05-21 22:03:003105 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223106 EXPECT_EQ(L"", response->auth_challenge->realm);
3107 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3108
[email protected]10af5fe72011-01-31 16:17:253109 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223110
3111 // Now enter the right password.
[email protected]10af5fe72011-01-31 16:17:253112 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
3113 EXPECT_EQ(ERR_IO_PENDING, rv);
3114
3115 rv = callback4.WaitForResult();
3116 EXPECT_EQ(OK, rv);
3117
3118 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3119
3120 TestCompletionCallback callback5;
3121
3122 // One more roundtrip
3123 rv = trans->RestartWithAuth(string16(), string16(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423124 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223125
3126 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423127 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223128
[email protected]385a4672009-03-11 22:21:293129 response = trans->GetResponseInfo();
3130 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3131 EXPECT_EQ(13, response->headers->GetContentLength());
3132}
[email protected]ea9dc9a2009-09-05 00:43:323133#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293134
[email protected]4ddaf2502008-10-23 18:26:193135// Test reading a server response which has only headers, and no body.
3136// After some maximum number of bytes is consumed, the transaction should
3137// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3138TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423139 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193140 request.method = "GET";
3141 request.url = GURL("http://www.google.com/");
3142 request.load_flags = 0;
3143
[email protected]cb9bf6ca2011-01-28 13:15:273144 SessionDependencies session_deps;
3145 scoped_ptr<HttpTransaction> trans(
3146 new HttpNetworkTransaction(CreateSession(&session_deps)));
3147
[email protected]b75b7b2f2009-10-06 00:54:533148 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433149 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533150 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193151
3152 MockRead data_reads[] = {
3153 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433154 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193155 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423156 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193157 };
[email protected]31a2bfe2010-02-09 08:03:393158 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593159 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193160
3161 TestCompletionCallback callback;
3162
[email protected]5a1d7ca2010-04-28 20:12:273163 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423164 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193165
3166 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423167 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193168
[email protected]1c773ea12009-04-28 19:58:423169 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193170 EXPECT_TRUE(response == NULL);
3171}
[email protected]f4e426b2008-11-05 00:24:493172
3173// Make sure that we don't try to reuse a TCPClientSocket when failing to
3174// establish tunnel.
3175// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283176TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273177 HttpRequestInfo request;
3178 request.method = "GET";
3179 request.url = GURL("https://www.google.com/");
3180 request.load_flags = 0;
3181
[email protected]f4e426b2008-11-05 00:24:493182 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003183 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013184
[email protected]228ff742009-06-05 01:19:593185 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493186
[email protected]5695b8c2009-09-30 21:36:433187 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493188
[email protected]f4e426b2008-11-05 00:24:493189 // Since we have proxy, should try to establish tunnel.
3190 MockWrite data_writes1[] = {
3191 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453192 "Host: www.google.com\r\n"
3193 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493194 };
3195
[email protected]77848d12008-11-14 00:00:223196 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493197 // connection. Usually a proxy would return 501 (not implemented),
3198 // or 200 (tunnel established).
3199 MockRead data_reads1[] = {
3200 MockRead("HTTP/1.1 404 Not Found\r\n"),
3201 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423202 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493203 };
3204
[email protected]31a2bfe2010-02-09 08:03:393205 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3206 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593207 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493208
3209 TestCompletionCallback callback1;
3210
[email protected]5a1d7ca2010-04-28 20:12:273211 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423212 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493213
3214 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423215 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493216
[email protected]1c773ea12009-04-28 19:58:423217 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083218 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493219
[email protected]b4404c02009-04-10 16:38:523220 // Empty the current queue. This is necessary because idle sockets are
3221 // added to the connection pool asynchronously with a PostTask.
3222 MessageLoop::current()->RunAllPending();
3223
[email protected]f4e426b2008-11-05 00:24:493224 // We now check to make sure the TCPClientSocket was not added back to
3225 // the pool.
[email protected]ab739042011-04-07 15:22:283226 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493227 trans.reset();
[email protected]b4404c02009-04-10 16:38:523228 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493229 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]ab739042011-04-07 15:22:283230 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493231}
[email protected]372d34a2008-11-05 21:30:513232
[email protected]1b157c02009-04-21 01:55:403233// Make sure that we recycle a socket after reading all of the response body.
3234TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423235 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403236 request.method = "GET";
3237 request.url = GURL("http://www.google.com/");
3238 request.load_flags = 0;
3239
[email protected]cb9bf6ca2011-01-28 13:15:273240 SessionDependencies session_deps;
3241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3242
3243 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3244
[email protected]1b157c02009-04-21 01:55:403245 MockRead data_reads[] = {
3246 // A part of the response body is received with the response headers.
3247 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3248 // The rest of the response body is received in two parts.
3249 MockRead("lo"),
3250 MockRead(" world"),
3251 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423252 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403253 };
3254
[email protected]31a2bfe2010-02-09 08:03:393255 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593256 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403257
3258 TestCompletionCallback callback;
3259
[email protected]5a1d7ca2010-04-28 20:12:273260 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423261 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403262
3263 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423264 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403265
[email protected]1c773ea12009-04-28 19:58:423266 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403267 EXPECT_TRUE(response != NULL);
3268
3269 EXPECT_TRUE(response->headers != NULL);
3270 std::string status_line = response->headers->GetStatusLine();
3271 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3272
[email protected]ab739042011-04-07 15:22:283273 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403274
3275 std::string response_data;
3276 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423277 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403278 EXPECT_EQ("hello world", response_data);
3279
3280 // Empty the current queue. This is necessary because idle sockets are
3281 // added to the connection pool asynchronously with a PostTask.
3282 MessageLoop::current()->RunAllPending();
3283
3284 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283285 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403286}
3287
[email protected]76a505b2010-08-25 06:23:003288// Make sure that we recycle a SSL socket after reading all of the response
3289// body.
3290TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3291 SessionDependencies session_deps;
3292 HttpRequestInfo request;
3293 request.method = "GET";
3294 request.url = GURL("https://www.google.com/");
3295 request.load_flags = 0;
3296
3297 MockWrite data_writes[] = {
3298 MockWrite("GET / HTTP/1.1\r\n"
3299 "Host: www.google.com\r\n"
3300 "Connection: keep-alive\r\n\r\n"),
3301 };
3302
3303 MockRead data_reads[] = {
3304 MockRead("HTTP/1.1 200 OK\r\n"),
3305 MockRead("Content-Length: 11\r\n\r\n"),
3306 MockRead("hello world"),
3307 MockRead(false, OK),
3308 };
3309
3310 SSLSocketDataProvider ssl(true, OK);
3311 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3312
3313 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3314 data_writes, arraysize(data_writes));
3315 session_deps.socket_factory.AddSocketDataProvider(&data);
3316
3317 TestCompletionCallback callback;
3318
3319 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3320 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3321
3322 int rv = trans->Start(&request, &callback, BoundNetLog());
3323
3324 EXPECT_EQ(ERR_IO_PENDING, rv);
3325 EXPECT_EQ(OK, callback.WaitForResult());
3326
3327 const HttpResponseInfo* response = trans->GetResponseInfo();
3328 ASSERT_TRUE(response != NULL);
3329 ASSERT_TRUE(response->headers != NULL);
3330 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3331
[email protected]ab739042011-04-07 15:22:283332 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003333
3334 std::string response_data;
3335 rv = ReadTransaction(trans.get(), &response_data);
3336 EXPECT_EQ(OK, rv);
3337 EXPECT_EQ("hello world", response_data);
3338
3339 // Empty the current queue. This is necessary because idle sockets are
3340 // added to the connection pool asynchronously with a PostTask.
3341 MessageLoop::current()->RunAllPending();
3342
3343 // We now check to make sure the socket was added back to the pool.
3344 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3345}
3346
3347// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3348// from the pool and make sure that we recover okay.
3349TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3350 SessionDependencies session_deps;
3351 HttpRequestInfo request;
3352 request.method = "GET";
3353 request.url = GURL("https://www.google.com/");
3354 request.load_flags = 0;
3355
3356 MockWrite data_writes[] = {
3357 MockWrite("GET / HTTP/1.1\r\n"
3358 "Host: www.google.com\r\n"
3359 "Connection: keep-alive\r\n\r\n"),
3360 MockWrite("GET / HTTP/1.1\r\n"
3361 "Host: www.google.com\r\n"
3362 "Connection: keep-alive\r\n\r\n"),
3363 };
3364
3365 MockRead data_reads[] = {
3366 MockRead("HTTP/1.1 200 OK\r\n"),
3367 MockRead("Content-Length: 11\r\n\r\n"),
3368 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3369 MockRead("hello world"),
3370 MockRead(true, 0, 0) // EOF
3371 };
3372
3373 SSLSocketDataProvider ssl(true, OK);
3374 SSLSocketDataProvider ssl2(true, OK);
3375 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3376 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3377
3378 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3379 data_writes, arraysize(data_writes));
3380 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3381 data_writes, arraysize(data_writes));
3382 session_deps.socket_factory.AddSocketDataProvider(&data);
3383 session_deps.socket_factory.AddSocketDataProvider(&data2);
3384
3385 TestCompletionCallback callback;
3386
3387 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3388 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3389
3390 int rv = trans->Start(&request, &callback, BoundNetLog());
3391
3392 EXPECT_EQ(ERR_IO_PENDING, rv);
3393 EXPECT_EQ(OK, callback.WaitForResult());
3394
3395 const HttpResponseInfo* response = trans->GetResponseInfo();
3396 ASSERT_TRUE(response != NULL);
3397 ASSERT_TRUE(response->headers != NULL);
3398 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3399
[email protected]ab739042011-04-07 15:22:283400 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003401
3402 std::string response_data;
3403 rv = ReadTransaction(trans.get(), &response_data);
3404 EXPECT_EQ(OK, rv);
3405 EXPECT_EQ("hello world", response_data);
3406
3407 // Empty the current queue. This is necessary because idle sockets are
3408 // added to the connection pool asynchronously with a PostTask.
3409 MessageLoop::current()->RunAllPending();
3410
3411 // We now check to make sure the socket was added back to the pool.
3412 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3413
3414 // Now start the second transaction, which should reuse the previous socket.
3415
3416 trans.reset(new HttpNetworkTransaction(session));
3417
3418 rv = trans->Start(&request, &callback, BoundNetLog());
3419
3420 EXPECT_EQ(ERR_IO_PENDING, rv);
3421 EXPECT_EQ(OK, callback.WaitForResult());
3422
3423 response = trans->GetResponseInfo();
3424 ASSERT_TRUE(response != NULL);
3425 ASSERT_TRUE(response->headers != NULL);
3426 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3427
[email protected]ab739042011-04-07 15:22:283428 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003429
3430 rv = ReadTransaction(trans.get(), &response_data);
3431 EXPECT_EQ(OK, rv);
3432 EXPECT_EQ("hello world", response_data);
3433
3434 // Empty the current queue. This is necessary because idle sockets are
3435 // added to the connection pool asynchronously with a PostTask.
3436 MessageLoop::current()->RunAllPending();
3437
3438 // We now check to make sure the socket was added back to the pool.
3439 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3440}
3441
[email protected]b4404c02009-04-10 16:38:523442// Make sure that we recycle a socket after a zero-length response.
3443// http://crbug.com/9880
3444TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423445 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523446 request.method = "GET";
3447 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3448 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3449 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3450 "rt=prt.2642,ol.2649,xjs.2951");
3451 request.load_flags = 0;
3452
[email protected]cb9bf6ca2011-01-28 13:15:273453 SessionDependencies session_deps;
3454 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3455
3456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3457
[email protected]b4404c02009-04-10 16:38:523458 MockRead data_reads[] = {
3459 MockRead("HTTP/1.1 204 No Content\r\n"
3460 "Content-Length: 0\r\n"
3461 "Content-Type: text/html\r\n\r\n"),
3462 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423463 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523464 };
3465
[email protected]31a2bfe2010-02-09 08:03:393466 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593467 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523468
3469 TestCompletionCallback callback;
3470
[email protected]5a1d7ca2010-04-28 20:12:273471 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423472 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523473
3474 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423475 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523476
[email protected]1c773ea12009-04-28 19:58:423477 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523478 EXPECT_TRUE(response != NULL);
3479
3480 EXPECT_TRUE(response->headers != NULL);
3481 std::string status_line = response->headers->GetStatusLine();
3482 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3483
[email protected]ab739042011-04-07 15:22:283484 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523485
3486 std::string response_data;
3487 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423488 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523489 EXPECT_EQ("", response_data);
3490
3491 // Empty the current queue. This is necessary because idle sockets are
3492 // added to the connection pool asynchronously with a PostTask.
3493 MessageLoop::current()->RunAllPending();
3494
3495 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283496 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523497}
3498
[email protected]372d34a2008-11-05 21:30:513499TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423500 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513501 // Transaction 1: a GET request that succeeds. The socket is recycled
3502 // after use.
3503 request[0].method = "GET";
3504 request[0].url = GURL("http://www.google.com/");
3505 request[0].load_flags = 0;
3506 // Transaction 2: a POST request. Reuses the socket kept alive from
3507 // transaction 1. The first attempts fails when writing the POST data.
3508 // This causes the transaction to retry with a new socket. The second
3509 // attempt succeeds.
3510 request[1].method = "POST";
3511 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423512 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513513 request[1].upload_data->AppendBytes("foo", 3);
3514 request[1].load_flags = 0;
3515
[email protected]228ff742009-06-05 01:19:593516 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273517 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513518
3519 // The first socket is used for transaction 1 and the first attempt of
3520 // transaction 2.
3521
3522 // The response of transaction 1.
3523 MockRead data_reads1[] = {
3524 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3525 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423526 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513527 };
3528 // The mock write results of transaction 1 and the first attempt of
3529 // transaction 2.
3530 MockWrite data_writes1[] = {
3531 MockWrite(false, 64), // GET
3532 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423533 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513534 };
[email protected]31a2bfe2010-02-09 08:03:393535 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3536 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513537
3538 // The second socket is used for the second attempt of transaction 2.
3539
3540 // The response of transaction 2.
3541 MockRead data_reads2[] = {
3542 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3543 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423544 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513545 };
3546 // The mock write results of the second attempt of transaction 2.
3547 MockWrite data_writes2[] = {
3548 MockWrite(false, 93), // POST
3549 MockWrite(false, 3), // POST data
3550 };
[email protected]31a2bfe2010-02-09 08:03:393551 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3552 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513553
[email protected]5ecc992a42009-11-11 01:41:593554 session_deps.socket_factory.AddSocketDataProvider(&data1);
3555 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513556
3557 const char* kExpectedResponseData[] = {
3558 "hello world", "welcome"
3559 };
3560
3561 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423562 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433563 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513564
3565 TestCompletionCallback callback;
3566
[email protected]5a1d7ca2010-04-28 20:12:273567 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423568 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513569
3570 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423571 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513572
[email protected]1c773ea12009-04-28 19:58:423573 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513574 EXPECT_TRUE(response != NULL);
3575
3576 EXPECT_TRUE(response->headers != NULL);
3577 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3578
3579 std::string response_data;
3580 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423581 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513582 EXPECT_EQ(kExpectedResponseData[i], response_data);
3583 }
3584}
[email protected]f9ee6b52008-11-08 06:46:233585
3586// Test the request-challenge-retry sequence for basic auth when there is
3587// an identity in the URL. The request should be sent as normal, but when
3588// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323589TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423590 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233591 request.method = "GET";
3592 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293593 request.url = GURL("http://foo:b@[email protected]/");
3594
[email protected]cb9bf6ca2011-01-28 13:15:273595 SessionDependencies session_deps;
3596 scoped_ptr<HttpTransaction> trans(
3597 new HttpNetworkTransaction(CreateSession(&session_deps)));
3598
[email protected]a97cca42009-08-14 01:00:293599 // The password contains an escaped character -- for this test to pass it
3600 // will need to be unescaped by HttpNetworkTransaction.
3601 EXPECT_EQ("b%40r", request.url.password());
3602
[email protected]ea9dc9a2009-09-05 00:43:323603 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233604
3605 MockWrite data_writes1[] = {
3606 MockWrite("GET / HTTP/1.1\r\n"
3607 "Host: www.google.com\r\n"
3608 "Connection: keep-alive\r\n\r\n"),
3609 };
3610
3611 MockRead data_reads1[] = {
3612 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3613 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3614 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423615 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233616 };
3617
3618 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323619 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233620 MockWrite data_writes2[] = {
3621 MockWrite("GET / HTTP/1.1\r\n"
3622 "Host: www.google.com\r\n"
3623 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293624 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233625 };
3626
3627 MockRead data_reads2[] = {
3628 MockRead("HTTP/1.0 200 OK\r\n"),
3629 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423630 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233631 };
3632
[email protected]31a2bfe2010-02-09 08:03:393633 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3634 data_writes1, arraysize(data_writes1));
3635 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3636 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593637 session_deps.socket_factory.AddSocketDataProvider(&data1);
3638 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233639
3640 TestCompletionCallback callback1;
3641
[email protected]5a1d7ca2010-04-28 20:12:273642 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423643 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233644
3645 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423646 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233647
[email protected]0757e7702009-03-27 04:00:223648 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3649 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443650 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423651 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223652 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423653 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223654 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3655
[email protected]1c773ea12009-04-28 19:58:423656 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233657 EXPECT_FALSE(response == NULL);
3658
3659 // There is no challenge info, since the identity in URL worked.
3660 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3661
3662 EXPECT_EQ(100, response->headers->GetContentLength());
3663
3664 // Empty the current queue.
3665 MessageLoop::current()->RunAllPending();
3666}
3667
[email protected]ea9dc9a2009-09-05 00:43:323668// Test the request-challenge-retry sequence for basic auth when there is
3669// an incorrect identity in the URL. The identity from the URL should be used
3670// only once.
3671TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323672 HttpRequestInfo request;
3673 request.method = "GET";
3674 // Note: the URL has a username:password in it. The password "baz" is
3675 // wrong (should be "bar").
3676 request.url = GURL("http://foo:[email protected]/");
3677
3678 request.load_flags = LOAD_NORMAL;
3679
[email protected]cb9bf6ca2011-01-28 13:15:273680 SessionDependencies session_deps;
3681 scoped_ptr<HttpTransaction> trans(
3682 new HttpNetworkTransaction(CreateSession(&session_deps)));
3683
[email protected]ea9dc9a2009-09-05 00:43:323684 MockWrite data_writes1[] = {
3685 MockWrite("GET / HTTP/1.1\r\n"
3686 "Host: www.google.com\r\n"
3687 "Connection: keep-alive\r\n\r\n"),
3688 };
3689
3690 MockRead data_reads1[] = {
3691 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3692 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3693 MockRead("Content-Length: 10\r\n\r\n"),
3694 MockRead(false, ERR_FAILED),
3695 };
3696
3697 // After the challenge above, the transaction will be restarted using the
3698 // identity from the url (foo, baz) to answer the challenge.
3699 MockWrite data_writes2[] = {
3700 MockWrite("GET / HTTP/1.1\r\n"
3701 "Host: www.google.com\r\n"
3702 "Connection: keep-alive\r\n"
3703 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3704 };
3705
3706 MockRead data_reads2[] = {
3707 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3708 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3709 MockRead("Content-Length: 10\r\n\r\n"),
3710 MockRead(false, ERR_FAILED),
3711 };
3712
3713 // After the challenge above, the transaction will be restarted using the
3714 // identity supplied by the user (foo, bar) to answer the challenge.
3715 MockWrite data_writes3[] = {
3716 MockWrite("GET / HTTP/1.1\r\n"
3717 "Host: www.google.com\r\n"
3718 "Connection: keep-alive\r\n"
3719 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3720 };
3721
3722 MockRead data_reads3[] = {
3723 MockRead("HTTP/1.0 200 OK\r\n"),
3724 MockRead("Content-Length: 100\r\n\r\n"),
3725 MockRead(false, OK),
3726 };
3727
[email protected]31a2bfe2010-02-09 08:03:393728 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3729 data_writes1, arraysize(data_writes1));
3730 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3731 data_writes2, arraysize(data_writes2));
3732 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3733 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593734 session_deps.socket_factory.AddSocketDataProvider(&data1);
3735 session_deps.socket_factory.AddSocketDataProvider(&data2);
3736 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323737
3738 TestCompletionCallback callback1;
3739
[email protected]5a1d7ca2010-04-28 20:12:273740 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323741 EXPECT_EQ(ERR_IO_PENDING, rv);
3742
3743 rv = callback1.WaitForResult();
3744 EXPECT_EQ(OK, rv);
3745
3746 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3747 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443748 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323749 EXPECT_EQ(ERR_IO_PENDING, rv);
3750 rv = callback2.WaitForResult();
3751 EXPECT_EQ(OK, rv);
3752 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3753
3754 const HttpResponseInfo* response = trans->GetResponseInfo();
3755 EXPECT_FALSE(response == NULL);
3756 // The password prompt info should have been set in response->auth_challenge.
3757 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3758
3759 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3760 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3761 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3762
3763 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443764 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323765 EXPECT_EQ(ERR_IO_PENDING, rv);
3766 rv = callback3.WaitForResult();
3767 EXPECT_EQ(OK, rv);
3768 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3769
3770 response = trans->GetResponseInfo();
3771 EXPECT_FALSE(response == NULL);
3772
3773 // There is no challenge info, since the identity worked.
3774 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3775
3776 EXPECT_EQ(100, response->headers->GetContentLength());
3777
3778 // Empty the current queue.
3779 MessageLoop::current()->RunAllPending();
3780}
3781
[email protected]f9ee6b52008-11-08 06:46:233782// Test that previously tried username/passwords for a realm get re-used.
3783TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593784 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273785 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233786
3787 // Transaction 1: authenticate (foo, bar) on MyRealm1
3788 {
[email protected]1c773ea12009-04-28 19:58:423789 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233790 request.method = "GET";
3791 request.url = GURL("http://www.google.com/x/y/z");
3792 request.load_flags = 0;
3793
[email protected]cb9bf6ca2011-01-28 13:15:273794 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3795
[email protected]f9ee6b52008-11-08 06:46:233796 MockWrite data_writes1[] = {
3797 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3798 "Host: www.google.com\r\n"
3799 "Connection: keep-alive\r\n\r\n"),
3800 };
3801
3802 MockRead data_reads1[] = {
3803 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3804 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3805 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423806 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233807 };
3808
3809 // Resend with authorization (username=foo, password=bar)
3810 MockWrite data_writes2[] = {
3811 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3812 "Host: www.google.com\r\n"
3813 "Connection: keep-alive\r\n"
3814 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3815 };
3816
3817 // Sever accepts the authorization.
3818 MockRead data_reads2[] = {
3819 MockRead("HTTP/1.0 200 OK\r\n"),
3820 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423821 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233822 };
3823
[email protected]31a2bfe2010-02-09 08:03:393824 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3825 data_writes1, arraysize(data_writes1));
3826 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3827 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593828 session_deps.socket_factory.AddSocketDataProvider(&data1);
3829 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233830
3831 TestCompletionCallback callback1;
3832
[email protected]5a1d7ca2010-04-28 20:12:273833 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423834 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233835
3836 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423837 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233838
[email protected]1c773ea12009-04-28 19:58:423839 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233840 EXPECT_FALSE(response == NULL);
3841
3842 // The password prompt info should have been set in
3843 // response->auth_challenge.
3844 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3845
[email protected]71e4573a2009-05-21 22:03:003846 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233847 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3848 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3849
3850 TestCompletionCallback callback2;
3851
[email protected]13c8a092010-07-29 06:15:443852 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423853 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233854
3855 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423856 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233857
3858 response = trans->GetResponseInfo();
3859 EXPECT_FALSE(response == NULL);
3860 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3861 EXPECT_EQ(100, response->headers->GetContentLength());
3862 }
3863
3864 // ------------------------------------------------------------------------
3865
3866 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3867 {
[email protected]1c773ea12009-04-28 19:58:423868 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233869 request.method = "GET";
3870 // Note that Transaction 1 was at /x/y/z, so this is in the same
3871 // protection space as MyRealm1.
3872 request.url = GURL("http://www.google.com/x/y/a/b");
3873 request.load_flags = 0;
3874
[email protected]cb9bf6ca2011-01-28 13:15:273875 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3876
[email protected]f9ee6b52008-11-08 06:46:233877 MockWrite data_writes1[] = {
3878 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3879 "Host: www.google.com\r\n"
3880 "Connection: keep-alive\r\n"
3881 // Send preemptive authorization for MyRealm1
3882 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3883 };
3884
3885 // The server didn't like the preemptive authorization, and
3886 // challenges us for a different realm (MyRealm2).
3887 MockRead data_reads1[] = {
3888 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3889 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3890 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423891 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233892 };
3893
3894 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3895 MockWrite data_writes2[] = {
3896 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3897 "Host: www.google.com\r\n"
3898 "Connection: keep-alive\r\n"
3899 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3900 };
3901
3902 // Sever accepts the authorization.
3903 MockRead data_reads2[] = {
3904 MockRead("HTTP/1.0 200 OK\r\n"),
3905 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423906 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233907 };
3908
[email protected]31a2bfe2010-02-09 08:03:393909 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3910 data_writes1, arraysize(data_writes1));
3911 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3912 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593913 session_deps.socket_factory.AddSocketDataProvider(&data1);
3914 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233915
3916 TestCompletionCallback callback1;
3917
[email protected]5a1d7ca2010-04-28 20:12:273918 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423919 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233920
3921 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423922 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233923
[email protected]1c773ea12009-04-28 19:58:423924 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233925 EXPECT_FALSE(response == NULL);
3926
3927 // The password prompt info should have been set in
3928 // response->auth_challenge.
3929 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3930
[email protected]71e4573a2009-05-21 22:03:003931 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233932 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3933 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3934
3935 TestCompletionCallback callback2;
3936
[email protected]13c8a092010-07-29 06:15:443937 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423938 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233939
3940 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423941 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233942
3943 response = trans->GetResponseInfo();
3944 EXPECT_FALSE(response == NULL);
3945 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3946 EXPECT_EQ(100, response->headers->GetContentLength());
3947 }
3948
3949 // ------------------------------------------------------------------------
3950
3951 // Transaction 3: Resend a request in MyRealm's protection space --
3952 // succeed with preemptive authorization.
3953 {
[email protected]1c773ea12009-04-28 19:58:423954 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233955 request.method = "GET";
3956 request.url = GURL("http://www.google.com/x/y/z2");
3957 request.load_flags = 0;
3958
[email protected]cb9bf6ca2011-01-28 13:15:273959 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3960
[email protected]f9ee6b52008-11-08 06:46:233961 MockWrite data_writes1[] = {
3962 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3963 "Host: www.google.com\r\n"
3964 "Connection: keep-alive\r\n"
3965 // The authorization for MyRealm1 gets sent preemptively
3966 // (since the url is in the same protection space)
3967 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3968 };
3969
3970 // Sever accepts the preemptive authorization
3971 MockRead data_reads1[] = {
3972 MockRead("HTTP/1.0 200 OK\r\n"),
3973 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423974 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233975 };
3976
[email protected]31a2bfe2010-02-09 08:03:393977 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3978 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593979 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233980
3981 TestCompletionCallback callback1;
3982
[email protected]5a1d7ca2010-04-28 20:12:273983 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423984 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233985
3986 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423987 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233988
[email protected]1c773ea12009-04-28 19:58:423989 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233990 EXPECT_FALSE(response == NULL);
3991
3992 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3993 EXPECT_EQ(100, response->headers->GetContentLength());
3994 }
3995
3996 // ------------------------------------------------------------------------
3997
3998 // Transaction 4: request another URL in MyRealm (however the
3999 // url is not known to belong to the protection space, so no pre-auth).
4000 {
[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/x/1");
4004 request.load_flags = 0;
4005
[email protected]cb9bf6ca2011-01-28 13:15:274006 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4007
[email protected]f9ee6b52008-11-08 06:46:234008 MockWrite data_writes1[] = {
4009 MockWrite("GET /x/1 HTTP/1.1\r\n"
4010 "Host: www.google.com\r\n"
4011 "Connection: keep-alive\r\n\r\n"),
4012 };
4013
4014 MockRead data_reads1[] = {
4015 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4016 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4017 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424018 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234019 };
4020
4021 // Resend with authorization from MyRealm's cache.
4022 MockWrite data_writes2[] = {
4023 MockWrite("GET /x/1 HTTP/1.1\r\n"
4024 "Host: www.google.com\r\n"
4025 "Connection: keep-alive\r\n"
4026 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4027 };
4028
4029 // Sever accepts the authorization.
4030 MockRead data_reads2[] = {
4031 MockRead("HTTP/1.0 200 OK\r\n"),
4032 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424033 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234034 };
4035
[email protected]31a2bfe2010-02-09 08:03:394036 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4037 data_writes1, arraysize(data_writes1));
4038 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4039 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594040 session_deps.socket_factory.AddSocketDataProvider(&data1);
4041 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234042
4043 TestCompletionCallback callback1;
4044
[email protected]5a1d7ca2010-04-28 20:12:274045 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424046 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234047
4048 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424049 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234050
[email protected]0757e7702009-03-27 04:00:224051 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4052 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444053 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424054 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224055 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424056 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224057 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4058
[email protected]1c773ea12009-04-28 19:58:424059 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234060 EXPECT_FALSE(response == NULL);
4061 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4062 EXPECT_EQ(100, response->headers->GetContentLength());
4063 }
4064
4065 // ------------------------------------------------------------------------
4066
4067 // Transaction 5: request a URL in MyRealm, but the server rejects the
4068 // cached identity. Should invalidate and re-prompt.
4069 {
[email protected]1c773ea12009-04-28 19:58:424070 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234071 request.method = "GET";
4072 request.url = GURL("http://www.google.com/p/q/t");
4073 request.load_flags = 0;
4074
[email protected]cb9bf6ca2011-01-28 13:15:274075 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4076
[email protected]f9ee6b52008-11-08 06:46:234077 MockWrite data_writes1[] = {
4078 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4079 "Host: www.google.com\r\n"
4080 "Connection: keep-alive\r\n\r\n"),
4081 };
4082
4083 MockRead data_reads1[] = {
4084 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4085 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4086 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424087 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234088 };
4089
4090 // Resend with authorization from cache for MyRealm.
4091 MockWrite data_writes2[] = {
4092 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4093 "Host: www.google.com\r\n"
4094 "Connection: keep-alive\r\n"
4095 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4096 };
4097
4098 // Sever rejects the authorization.
4099 MockRead data_reads2[] = {
4100 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4101 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4102 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424103 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234104 };
4105
4106 // At this point we should prompt for new credentials for MyRealm.
4107 // Restart with username=foo3, password=foo4.
4108 MockWrite data_writes3[] = {
4109 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4110 "Host: www.google.com\r\n"
4111 "Connection: keep-alive\r\n"
4112 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4113 };
4114
4115 // Sever accepts the authorization.
4116 MockRead data_reads3[] = {
4117 MockRead("HTTP/1.0 200 OK\r\n"),
4118 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424119 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234120 };
4121
[email protected]31a2bfe2010-02-09 08:03:394122 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4123 data_writes1, arraysize(data_writes1));
4124 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4125 data_writes2, arraysize(data_writes2));
4126 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4127 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594128 session_deps.socket_factory.AddSocketDataProvider(&data1);
4129 session_deps.socket_factory.AddSocketDataProvider(&data2);
4130 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234131
4132 TestCompletionCallback callback1;
4133
[email protected]5a1d7ca2010-04-28 20:12:274134 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424135 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234136
4137 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424138 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234139
[email protected]0757e7702009-03-27 04:00:224140 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4141 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444142 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424143 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224144 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424145 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224146 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4147
[email protected]1c773ea12009-04-28 19:58:424148 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234149 EXPECT_FALSE(response == NULL);
4150
4151 // The password prompt info should have been set in
4152 // response->auth_challenge.
4153 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4154
[email protected]71e4573a2009-05-21 22:03:004155 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234156 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4157 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4158
[email protected]0757e7702009-03-27 04:00:224159 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234160
[email protected]13c8a092010-07-29 06:15:444161 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424162 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234163
[email protected]0757e7702009-03-27 04:00:224164 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424165 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234166
4167 response = trans->GetResponseInfo();
4168 EXPECT_FALSE(response == NULL);
4169 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4170 EXPECT_EQ(100, response->headers->GetContentLength());
4171 }
4172}
[email protected]89ceba9a2009-03-21 03:46:064173
[email protected]3c32c5f2010-05-18 15:18:124174// Tests that nonce count increments when multiple auth attempts
4175// are started with the same nonce.
4176TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4177 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444178 HttpAuthHandlerDigest::Factory* digest_factory =
4179 new HttpAuthHandlerDigest::Factory();
4180 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4181 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4182 digest_factory->set_nonce_generator(nonce_generator);
4183 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274184 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124185
4186 // Transaction 1: authenticate (foo, bar) on MyRealm1
4187 {
[email protected]3c32c5f2010-05-18 15:18:124188 HttpRequestInfo request;
4189 request.method = "GET";
4190 request.url = GURL("http://www.google.com/x/y/z");
4191 request.load_flags = 0;
4192
[email protected]cb9bf6ca2011-01-28 13:15:274193 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4194
[email protected]3c32c5f2010-05-18 15:18:124195 MockWrite data_writes1[] = {
4196 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4197 "Host: www.google.com\r\n"
4198 "Connection: keep-alive\r\n\r\n"),
4199 };
4200
4201 MockRead data_reads1[] = {
4202 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4203 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4204 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4205 MockRead(false, OK),
4206 };
4207
4208 // Resend with authorization (username=foo, password=bar)
4209 MockWrite data_writes2[] = {
4210 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4211 "Host: www.google.com\r\n"
4212 "Connection: keep-alive\r\n"
4213 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4214 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4215 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4216 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4217 };
4218
4219 // Sever accepts the authorization.
4220 MockRead data_reads2[] = {
4221 MockRead("HTTP/1.0 200 OK\r\n"),
4222 MockRead(false, OK),
4223 };
4224
4225 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4226 data_writes1, arraysize(data_writes1));
4227 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4228 data_writes2, arraysize(data_writes2));
4229 session_deps.socket_factory.AddSocketDataProvider(&data1);
4230 session_deps.socket_factory.AddSocketDataProvider(&data2);
4231
4232 TestCompletionCallback callback1;
4233
4234 int rv = trans->Start(&request, &callback1, BoundNetLog());
4235 EXPECT_EQ(ERR_IO_PENDING, rv);
4236
4237 rv = callback1.WaitForResult();
4238 EXPECT_EQ(OK, rv);
4239
4240 const HttpResponseInfo* response = trans->GetResponseInfo();
4241 ASSERT_FALSE(response == NULL);
4242
4243 // The password prompt info should have been set in
4244 // response->auth_challenge.
4245 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4246
4247 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4248 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4249 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4250
4251 TestCompletionCallback callback2;
4252
[email protected]13c8a092010-07-29 06:15:444253 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124254 EXPECT_EQ(ERR_IO_PENDING, rv);
4255
4256 rv = callback2.WaitForResult();
4257 EXPECT_EQ(OK, rv);
4258
4259 response = trans->GetResponseInfo();
4260 ASSERT_FALSE(response == NULL);
4261 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4262 }
4263
4264 // ------------------------------------------------------------------------
4265
4266 // Transaction 2: Request another resource in digestive's protection space.
4267 // This will preemptively add an Authorization header which should have an
4268 // "nc" value of 2 (as compared to 1 in the first use.
4269 {
[email protected]3c32c5f2010-05-18 15:18:124270 HttpRequestInfo request;
4271 request.method = "GET";
4272 // Note that Transaction 1 was at /x/y/z, so this is in the same
4273 // protection space as digest.
4274 request.url = GURL("http://www.google.com/x/y/a/b");
4275 request.load_flags = 0;
4276
[email protected]cb9bf6ca2011-01-28 13:15:274277 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4278
[email protected]3c32c5f2010-05-18 15:18:124279 MockWrite data_writes1[] = {
4280 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4281 "Host: www.google.com\r\n"
4282 "Connection: keep-alive\r\n"
4283 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4284 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4285 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4286 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4287 };
4288
4289 // Sever accepts the authorization.
4290 MockRead data_reads1[] = {
4291 MockRead("HTTP/1.0 200 OK\r\n"),
4292 MockRead("Content-Length: 100\r\n\r\n"),
4293 MockRead(false, OK),
4294 };
4295
4296 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4297 data_writes1, arraysize(data_writes1));
4298 session_deps.socket_factory.AddSocketDataProvider(&data1);
4299
4300 TestCompletionCallback callback1;
4301
4302 int rv = trans->Start(&request, &callback1, BoundNetLog());
4303 EXPECT_EQ(ERR_IO_PENDING, rv);
4304
4305 rv = callback1.WaitForResult();
4306 EXPECT_EQ(OK, rv);
4307
4308 const HttpResponseInfo* response = trans->GetResponseInfo();
4309 ASSERT_FALSE(response == NULL);
4310 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4311 }
4312}
4313
[email protected]89ceba9a2009-03-21 03:46:064314// Test the ResetStateForRestart() private method.
4315TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4316 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594317 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404318 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434319 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064320
4321 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064322 trans->read_buf_ = new IOBuffer(15);
4323 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204324 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064325
4326 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144327 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574328 response->auth_challenge = new AuthChallengeInfo();
4329 response->ssl_info.cert_status = -15;
4330 response->response_time = base::Time::Now();
4331 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064332
4333 { // Setup state for response_.vary_data
4334 HttpRequestInfo request;
4335 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4336 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274337 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434338 request.extra_headers.SetHeader("Foo", "1");
4339 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574340 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064341 }
4342
4343 // Cause the above state to be reset.
4344 trans->ResetStateForRestart();
4345
4346 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074347 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064348 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204349 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574350 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4351 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044352 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574353 EXPECT_EQ(0, response->ssl_info.cert_status);
4354 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064355}
4356
[email protected]bacff652009-03-31 17:50:334357// Test HTTPS connections to a site with a bad certificate
4358TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334359 HttpRequestInfo request;
4360 request.method = "GET";
4361 request.url = GURL("https://www.google.com/");
4362 request.load_flags = 0;
4363
[email protected]cb9bf6ca2011-01-28 13:15:274364 SessionDependencies session_deps;
4365 scoped_ptr<HttpTransaction> trans(
4366 new HttpNetworkTransaction(CreateSession(&session_deps)));
4367
[email protected]bacff652009-03-31 17:50:334368 MockWrite data_writes[] = {
4369 MockWrite("GET / HTTP/1.1\r\n"
4370 "Host: www.google.com\r\n"
4371 "Connection: keep-alive\r\n\r\n"),
4372 };
4373
4374 MockRead data_reads[] = {
4375 MockRead("HTTP/1.0 200 OK\r\n"),
4376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4377 MockRead("Content-Length: 100\r\n\r\n"),
4378 MockRead(false, OK),
4379 };
4380
[email protected]5ecc992a42009-11-11 01:41:594381 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394382 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
[email protected]5a1d7ca2010-04-28 20:12:274394 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334395 EXPECT_EQ(ERR_IO_PENDING, rv);
4396
4397 rv = callback.WaitForResult();
4398 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4399
4400 rv = trans->RestartIgnoringLastError(&callback);
4401 EXPECT_EQ(ERR_IO_PENDING, rv);
4402
4403 rv = callback.WaitForResult();
4404 EXPECT_EQ(OK, rv);
4405
4406 const HttpResponseInfo* response = trans->GetResponseInfo();
4407
4408 EXPECT_FALSE(response == NULL);
4409 EXPECT_EQ(100, response->headers->GetContentLength());
4410}
4411
4412// Test HTTPS connections to a site with a bad certificate, going through a
4413// proxy
4414TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004415 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334416
4417 HttpRequestInfo request;
4418 request.method = "GET";
4419 request.url = GURL("https://www.google.com/");
4420 request.load_flags = 0;
4421
4422 MockWrite proxy_writes[] = {
4423 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454424 "Host: www.google.com\r\n"
4425 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334426 };
4427
4428 MockRead proxy_reads[] = {
4429 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424430 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334431 };
4432
4433 MockWrite data_writes[] = {
4434 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454435 "Host: www.google.com\r\n"
4436 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334437 MockWrite("GET / HTTP/1.1\r\n"
4438 "Host: www.google.com\r\n"
4439 "Connection: keep-alive\r\n\r\n"),
4440 };
4441
4442 MockRead data_reads[] = {
4443 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4444 MockRead("HTTP/1.0 200 OK\r\n"),
4445 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4446 MockRead("Content-Length: 100\r\n\r\n"),
4447 MockRead(false, OK),
4448 };
4449
[email protected]31a2bfe2010-02-09 08:03:394450 StaticSocketDataProvider ssl_bad_certificate(
4451 proxy_reads, arraysize(proxy_reads),
4452 proxy_writes, arraysize(proxy_writes));
4453 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4454 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594455 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4456 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334457
[email protected]5ecc992a42009-11-11 01:41:594458 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4459 session_deps.socket_factory.AddSocketDataProvider(&data);
4460 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4461 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334462
4463 TestCompletionCallback callback;
4464
4465 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594466 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334467
[email protected]d207a5f2009-06-04 05:28:404468 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434469 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334470
[email protected]5a1d7ca2010-04-28 20:12:274471 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334472 EXPECT_EQ(ERR_IO_PENDING, rv);
4473
4474 rv = callback.WaitForResult();
4475 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4476
4477 rv = trans->RestartIgnoringLastError(&callback);
4478 EXPECT_EQ(ERR_IO_PENDING, rv);
4479
4480 rv = callback.WaitForResult();
4481 EXPECT_EQ(OK, rv);
4482
4483 const HttpResponseInfo* response = trans->GetResponseInfo();
4484
4485 EXPECT_FALSE(response == NULL);
4486 EXPECT_EQ(100, response->headers->GetContentLength());
4487 }
4488}
4489
[email protected]2df19bb2010-08-25 20:13:464490
4491// Test HTTPS connections to a site, going through an HTTPS proxy
4492TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004493 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464494
4495 HttpRequestInfo request;
4496 request.method = "GET";
4497 request.url = GURL("https://www.google.com/");
4498 request.load_flags = 0;
4499
4500 MockWrite data_writes[] = {
4501 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4502 "Host: www.google.com\r\n"
4503 "Proxy-Connection: keep-alive\r\n\r\n"),
4504 MockWrite("GET / HTTP/1.1\r\n"
4505 "Host: www.google.com\r\n"
4506 "Connection: keep-alive\r\n\r\n"),
4507 };
4508
4509 MockRead data_reads[] = {
4510 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4511 MockRead("HTTP/1.1 200 OK\r\n"),
4512 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4513 MockRead("Content-Length: 100\r\n\r\n"),
4514 MockRead(false, OK),
4515 };
4516
4517 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4518 data_writes, arraysize(data_writes));
4519 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4520 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4521
4522 session_deps.socket_factory.AddSocketDataProvider(&data);
4523 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4524 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4525
4526 TestCompletionCallback callback;
4527
4528 scoped_ptr<HttpTransaction> trans(
4529 new HttpNetworkTransaction(CreateSession(&session_deps)));
4530
4531 int rv = trans->Start(&request, &callback, BoundNetLog());
4532 EXPECT_EQ(ERR_IO_PENDING, rv);
4533
4534 rv = callback.WaitForResult();
4535 EXPECT_EQ(OK, rv);
4536 const HttpResponseInfo* response = trans->GetResponseInfo();
4537
4538 ASSERT_FALSE(response == NULL);
4539
4540 EXPECT_TRUE(response->headers->IsKeepAlive());
4541 EXPECT_EQ(200, response->headers->response_code());
4542 EXPECT_EQ(100, response->headers->GetContentLength());
4543 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4544}
4545
[email protected]511f6f52010-12-17 03:58:294546// Test an HTTPS Proxy's ability to redirect a CONNECT request
4547TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4548 SessionDependencies session_deps(
4549 ProxyService::CreateFixed("https://proxy:70"));
4550
4551 HttpRequestInfo request;
4552 request.method = "GET";
4553 request.url = GURL("https://www.google.com/");
4554 request.load_flags = 0;
4555
4556 MockWrite data_writes[] = {
4557 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4558 "Host: www.google.com\r\n"
4559 "Proxy-Connection: keep-alive\r\n\r\n"),
4560 };
4561
4562 MockRead data_reads[] = {
4563 MockRead("HTTP/1.1 302 Redirect\r\n"),
4564 MockRead("Location: http://login.example.com/\r\n"),
4565 MockRead("Content-Length: 0\r\n\r\n"),
4566 MockRead(false, OK),
4567 };
4568
4569 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4570 data_writes, arraysize(data_writes));
4571 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4572
4573 session_deps.socket_factory.AddSocketDataProvider(&data);
4574 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4575
4576 TestCompletionCallback callback;
4577
4578 scoped_ptr<HttpTransaction> trans(
4579 new HttpNetworkTransaction(CreateSession(&session_deps)));
4580
4581 int rv = trans->Start(&request, &callback, BoundNetLog());
4582 EXPECT_EQ(ERR_IO_PENDING, rv);
4583
4584 rv = callback.WaitForResult();
4585 EXPECT_EQ(OK, rv);
4586 const HttpResponseInfo* response = trans->GetResponseInfo();
4587
4588 ASSERT_FALSE(response == NULL);
4589
4590 EXPECT_EQ(302, response->headers->response_code());
4591 std::string url;
4592 EXPECT_TRUE(response->headers->IsRedirect(&url));
4593 EXPECT_EQ("http://login.example.com/", url);
4594}
4595
4596// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4597TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4598 SessionDependencies session_deps(
4599 ProxyService::CreateFixed("https://proxy:70"));
4600
4601 HttpRequestInfo request;
4602 request.method = "GET";
4603 request.url = GURL("https://www.google.com/");
4604 request.load_flags = 0;
4605
4606 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4607 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4608 MockWrite data_writes[] = {
4609 CreateMockWrite(*conn.get(), 0, false),
4610 };
4611
4612 static const char* const kExtraHeaders[] = {
4613 "location",
4614 "http://login.example.com/",
4615 };
4616 scoped_ptr<spdy::SpdyFrame> resp(
4617 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4618 arraysize(kExtraHeaders)/2, 1));
4619 MockRead data_reads[] = {
4620 CreateMockRead(*resp.get(), 1, false),
4621 MockRead(true, 0, 2), // EOF
4622 };
4623
4624 scoped_refptr<DelayedSocketData> data(
4625 new DelayedSocketData(
4626 1, // wait for one write to finish before reading.
4627 data_reads, arraysize(data_reads),
4628 data_writes, arraysize(data_writes)));
4629 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4630 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4631 proxy_ssl.next_proto = "spdy/2";
4632 proxy_ssl.was_npn_negotiated = true;
4633
4634 session_deps.socket_factory.AddSocketDataProvider(data.get());
4635 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4636
4637 TestCompletionCallback callback;
4638
4639 scoped_ptr<HttpTransaction> trans(
4640 new HttpNetworkTransaction(CreateSession(&session_deps)));
4641
4642 int rv = trans->Start(&request, &callback, BoundNetLog());
4643 EXPECT_EQ(ERR_IO_PENDING, rv);
4644
4645 rv = callback.WaitForResult();
4646 EXPECT_EQ(OK, rv);
4647 const HttpResponseInfo* response = trans->GetResponseInfo();
4648
4649 ASSERT_FALSE(response == NULL);
4650
4651 EXPECT_EQ(302, response->headers->response_code());
4652 std::string url;
4653 EXPECT_TRUE(response->headers->IsRedirect(&url));
4654 EXPECT_EQ("http://login.example.com/", url);
4655}
4656
4657// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4658TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4659 SessionDependencies session_deps(
4660 ProxyService::CreateFixed("https://proxy:70"));
4661
4662 HttpRequestInfo request;
4663 request.method = "GET";
4664 request.url = GURL("https://www.google.com/");
4665 request.load_flags = 0;
4666
4667 MockWrite data_writes[] = {
4668 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4669 "Host: www.google.com\r\n"
4670 "Proxy-Connection: keep-alive\r\n\r\n"),
4671 };
4672
4673 MockRead data_reads[] = {
4674 MockRead("HTTP/1.1 404 Not Found\r\n"),
4675 MockRead("Content-Length: 23\r\n\r\n"),
4676 MockRead("The host does not exist"),
4677 MockRead(false, OK),
4678 };
4679
4680 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4681 data_writes, arraysize(data_writes));
4682 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4683
4684 session_deps.socket_factory.AddSocketDataProvider(&data);
4685 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4686
4687 TestCompletionCallback callback;
4688
4689 scoped_ptr<HttpTransaction> trans(
4690 new HttpNetworkTransaction(CreateSession(&session_deps)));
4691
4692 int rv = trans->Start(&request, &callback, BoundNetLog());
4693 EXPECT_EQ(ERR_IO_PENDING, rv);
4694
4695 rv = callback.WaitForResult();
4696 EXPECT_EQ(OK, rv);
4697 const HttpResponseInfo* response = trans->GetResponseInfo();
4698
4699 ASSERT_FALSE(response == NULL);
4700
4701 EXPECT_EQ(404, response->headers->response_code());
4702 EXPECT_EQ(23, response->headers->GetContentLength());
4703 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4704 EXPECT_FALSE(response->ssl_info.is_valid());
4705
4706 std::string response_data;
4707 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4708 EXPECT_EQ("The host does not exist", response_data);
4709}
4710
4711// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4712// request
4713TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4714 SessionDependencies session_deps(
4715 ProxyService::CreateFixed("https://proxy:70"));
4716
4717 HttpRequestInfo request;
4718 request.method = "GET";
4719 request.url = GURL("https://www.google.com/");
4720 request.load_flags = 0;
4721
4722 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4723 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4724 MockWrite data_writes[] = {
4725 CreateMockWrite(*conn.get(), 0, false),
4726 };
4727
4728 static const char* const kExtraHeaders[] = {
4729 "location",
4730 "http://login.example.com/",
4731 };
4732 scoped_ptr<spdy::SpdyFrame> resp(
4733 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4734 arraysize(kExtraHeaders)/2, 1));
4735 scoped_ptr<spdy::SpdyFrame> body(
4736 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4737 MockRead data_reads[] = {
4738 CreateMockRead(*resp.get(), 1, false),
4739 CreateMockRead(*body.get(), 2, false),
4740 MockRead(true, 0, 3), // EOF
4741 };
4742
4743 scoped_refptr<DelayedSocketData> data(
4744 new DelayedSocketData(
4745 1, // wait for one write to finish before reading.
4746 data_reads, arraysize(data_reads),
4747 data_writes, arraysize(data_writes)));
4748 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4749 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4750 proxy_ssl.next_proto = "spdy/2";
4751 proxy_ssl.was_npn_negotiated = true;
4752
4753 session_deps.socket_factory.AddSocketDataProvider(data.get());
4754 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4755
4756 TestCompletionCallback callback;
4757
4758 scoped_ptr<HttpTransaction> trans(
4759 new HttpNetworkTransaction(CreateSession(&session_deps)));
4760
4761 int rv = trans->Start(&request, &callback, BoundNetLog());
4762 EXPECT_EQ(ERR_IO_PENDING, rv);
4763
4764 rv = callback.WaitForResult();
4765 EXPECT_EQ(OK, rv);
4766 const HttpResponseInfo* response = trans->GetResponseInfo();
4767
4768 ASSERT_FALSE(response == NULL);
4769
4770 EXPECT_EQ(404, response->headers->response_code());
4771 EXPECT_FALSE(response->ssl_info.is_valid());
4772
4773 std::string response_data;
4774 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4775 EXPECT_EQ("The host does not exist", response_data);
4776}
4777
[email protected]2df19bb2010-08-25 20:13:464778// Test HTTPS connections to a site with a bad certificate, going through an
4779// HTTPS proxy
4780TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004781 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464782
4783 HttpRequestInfo request;
4784 request.method = "GET";
4785 request.url = GURL("https://www.google.com/");
4786 request.load_flags = 0;
4787
4788 // Attempt to fetch the URL from a server with a bad cert
4789 MockWrite bad_cert_writes[] = {
4790 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4791 "Host: www.google.com\r\n"
4792 "Proxy-Connection: keep-alive\r\n\r\n"),
4793 };
4794
4795 MockRead bad_cert_reads[] = {
4796 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4797 MockRead(false, OK)
4798 };
4799
4800 // Attempt to fetch the URL with a good cert
4801 MockWrite good_data_writes[] = {
4802 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4803 "Host: www.google.com\r\n"
4804 "Proxy-Connection: keep-alive\r\n\r\n"),
4805 MockWrite("GET / HTTP/1.1\r\n"
4806 "Host: www.google.com\r\n"
4807 "Connection: keep-alive\r\n\r\n"),
4808 };
4809
4810 MockRead good_cert_reads[] = {
4811 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4812 MockRead("HTTP/1.0 200 OK\r\n"),
4813 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4814 MockRead("Content-Length: 100\r\n\r\n"),
4815 MockRead(false, OK),
4816 };
4817
4818 StaticSocketDataProvider ssl_bad_certificate(
4819 bad_cert_reads, arraysize(bad_cert_reads),
4820 bad_cert_writes, arraysize(bad_cert_writes));
4821 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4822 good_data_writes, arraysize(good_data_writes));
4823 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4824 SSLSocketDataProvider ssl(true, OK);
4825
4826 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4827 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4828 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4829 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4830
4831 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4832 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4833 session_deps.socket_factory.AddSocketDataProvider(&data);
4834 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4835
4836 TestCompletionCallback callback;
4837
4838 scoped_ptr<HttpTransaction> trans(
4839 new HttpNetworkTransaction(CreateSession(&session_deps)));
4840
4841 int rv = trans->Start(&request, &callback, BoundNetLog());
4842 EXPECT_EQ(ERR_IO_PENDING, rv);
4843
4844 rv = callback.WaitForResult();
4845 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4846
4847 rv = trans->RestartIgnoringLastError(&callback);
4848 EXPECT_EQ(ERR_IO_PENDING, rv);
4849
4850 rv = callback.WaitForResult();
4851 EXPECT_EQ(OK, rv);
4852
4853 const HttpResponseInfo* response = trans->GetResponseInfo();
4854
4855 EXPECT_FALSE(response == NULL);
4856 EXPECT_EQ(100, response->headers->GetContentLength());
4857}
4858
[email protected]1c773ea12009-04-28 19:58:424859TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424860 HttpRequestInfo request;
4861 request.method = "GET";
4862 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434863 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4864 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424865
[email protected]cb9bf6ca2011-01-28 13:15:274866 SessionDependencies session_deps;
4867 scoped_ptr<HttpTransaction> trans(
4868 new HttpNetworkTransaction(CreateSession(&session_deps)));
4869
[email protected]1c773ea12009-04-28 19:58:424870 MockWrite data_writes[] = {
4871 MockWrite("GET / HTTP/1.1\r\n"
4872 "Host: www.google.com\r\n"
4873 "Connection: keep-alive\r\n"
4874 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4875 };
4876
4877 // Lastly, the server responds with the actual content.
4878 MockRead data_reads[] = {
4879 MockRead("HTTP/1.0 200 OK\r\n"),
4880 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4881 MockRead("Content-Length: 100\r\n\r\n"),
4882 MockRead(false, OK),
4883 };
4884
[email protected]31a2bfe2010-02-09 08:03:394885 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4886 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594887 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424888
4889 TestCompletionCallback callback;
4890
[email protected]5a1d7ca2010-04-28 20:12:274891 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424892 EXPECT_EQ(ERR_IO_PENDING, rv);
4893
4894 rv = callback.WaitForResult();
4895 EXPECT_EQ(OK, rv);
4896}
4897
[email protected]da81f132010-08-18 23:39:294898TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294899 HttpRequestInfo request;
4900 request.method = "GET";
4901 request.url = GURL("https://www.google.com/");
4902 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4903 "Chromium Ultra Awesome X Edition");
4904
[email protected]cb9bf6ca2011-01-28 13:15:274905 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4906 scoped_ptr<HttpTransaction> trans(
4907 new HttpNetworkTransaction(CreateSession(&session_deps)));
4908
[email protected]da81f132010-08-18 23:39:294909 MockWrite data_writes[] = {
4910 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4911 "Host: www.google.com\r\n"
4912 "Proxy-Connection: keep-alive\r\n"
4913 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4914 };
4915 MockRead data_reads[] = {
4916 // Return an error, so the transaction stops here (this test isn't
4917 // interested in the rest).
4918 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4919 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4920 MockRead("Proxy-Connection: close\r\n\r\n"),
4921 };
4922
4923 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4924 data_writes, arraysize(data_writes));
4925 session_deps.socket_factory.AddSocketDataProvider(&data);
4926
4927 TestCompletionCallback callback;
4928
4929 int rv = trans->Start(&request, &callback, BoundNetLog());
4930 EXPECT_EQ(ERR_IO_PENDING, rv);
4931
4932 rv = callback.WaitForResult();
4933 EXPECT_EQ(OK, rv);
4934}
4935
[email protected]1c773ea12009-04-28 19:58:424936TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424937 HttpRequestInfo request;
4938 request.method = "GET";
4939 request.url = GURL("http://www.google.com/");
4940 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:164941 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
4942 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:424943
[email protected]cb9bf6ca2011-01-28 13:15:274944 SessionDependencies session_deps;
4945 scoped_ptr<HttpTransaction> trans(
4946 new HttpNetworkTransaction(CreateSession(&session_deps)));
4947
[email protected]1c773ea12009-04-28 19:58:424948 MockWrite data_writes[] = {
4949 MockWrite("GET / HTTP/1.1\r\n"
4950 "Host: www.google.com\r\n"
4951 "Connection: keep-alive\r\n"
4952 "Referer: http://the.previous.site.com/\r\n\r\n"),
4953 };
4954
4955 // Lastly, the server responds with the actual content.
4956 MockRead data_reads[] = {
4957 MockRead("HTTP/1.0 200 OK\r\n"),
4958 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4959 MockRead("Content-Length: 100\r\n\r\n"),
4960 MockRead(false, OK),
4961 };
4962
[email protected]31a2bfe2010-02-09 08:03:394963 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4964 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594965 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424966
4967 TestCompletionCallback callback;
4968
[email protected]5a1d7ca2010-04-28 20:12:274969 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424970 EXPECT_EQ(ERR_IO_PENDING, rv);
4971
4972 rv = callback.WaitForResult();
4973 EXPECT_EQ(OK, rv);
4974}
4975
4976TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424977 HttpRequestInfo request;
4978 request.method = "POST";
4979 request.url = GURL("http://www.google.com/");
4980
[email protected]cb9bf6ca2011-01-28 13:15:274981 SessionDependencies session_deps;
4982 scoped_ptr<HttpTransaction> trans(
4983 new HttpNetworkTransaction(CreateSession(&session_deps)));
4984
[email protected]1c773ea12009-04-28 19:58:424985 MockWrite data_writes[] = {
4986 MockWrite("POST / HTTP/1.1\r\n"
4987 "Host: www.google.com\r\n"
4988 "Connection: keep-alive\r\n"
4989 "Content-Length: 0\r\n\r\n"),
4990 };
4991
4992 // Lastly, the server responds with the actual content.
4993 MockRead data_reads[] = {
4994 MockRead("HTTP/1.0 200 OK\r\n"),
4995 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4996 MockRead("Content-Length: 100\r\n\r\n"),
4997 MockRead(false, OK),
4998 };
4999
[email protected]31a2bfe2010-02-09 08:03:395000 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5001 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595002 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425003
5004 TestCompletionCallback callback;
5005
[email protected]5a1d7ca2010-04-28 20:12:275006 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425007 EXPECT_EQ(ERR_IO_PENDING, rv);
5008
5009 rv = callback.WaitForResult();
5010 EXPECT_EQ(OK, rv);
5011}
5012
5013TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425014 HttpRequestInfo request;
5015 request.method = "PUT";
5016 request.url = GURL("http://www.google.com/");
5017
[email protected]cb9bf6ca2011-01-28 13:15:275018 SessionDependencies session_deps;
5019 scoped_ptr<HttpTransaction> trans(
5020 new HttpNetworkTransaction(CreateSession(&session_deps)));
5021
[email protected]1c773ea12009-04-28 19:58:425022 MockWrite data_writes[] = {
5023 MockWrite("PUT / HTTP/1.1\r\n"
5024 "Host: www.google.com\r\n"
5025 "Connection: keep-alive\r\n"
5026 "Content-Length: 0\r\n\r\n"),
5027 };
5028
5029 // Lastly, the server responds with the actual content.
5030 MockRead data_reads[] = {
5031 MockRead("HTTP/1.0 200 OK\r\n"),
5032 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5033 MockRead("Content-Length: 100\r\n\r\n"),
5034 MockRead(false, OK),
5035 };
5036
[email protected]31a2bfe2010-02-09 08:03:395037 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5038 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595039 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425040
5041 TestCompletionCallback callback;
5042
[email protected]5a1d7ca2010-04-28 20:12:275043 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425044 EXPECT_EQ(ERR_IO_PENDING, rv);
5045
5046 rv = callback.WaitForResult();
5047 EXPECT_EQ(OK, rv);
5048}
5049
5050TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425051 HttpRequestInfo request;
5052 request.method = "HEAD";
5053 request.url = GURL("http://www.google.com/");
5054
[email protected]cb9bf6ca2011-01-28 13:15:275055 SessionDependencies session_deps;
5056 scoped_ptr<HttpTransaction> trans(
5057 new HttpNetworkTransaction(CreateSession(&session_deps)));
5058
[email protected]1c773ea12009-04-28 19:58:425059 MockWrite data_writes[] = {
5060 MockWrite("HEAD / HTTP/1.1\r\n"
5061 "Host: www.google.com\r\n"
5062 "Connection: keep-alive\r\n"
5063 "Content-Length: 0\r\n\r\n"),
5064 };
5065
5066 // Lastly, the server responds with the actual content.
5067 MockRead data_reads[] = {
5068 MockRead("HTTP/1.0 200 OK\r\n"),
5069 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5070 MockRead("Content-Length: 100\r\n\r\n"),
5071 MockRead(false, OK),
5072 };
5073
[email protected]31a2bfe2010-02-09 08:03:395074 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5075 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595076 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425077
5078 TestCompletionCallback callback;
5079
[email protected]5a1d7ca2010-04-28 20:12:275080 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425081 EXPECT_EQ(ERR_IO_PENDING, rv);
5082
5083 rv = callback.WaitForResult();
5084 EXPECT_EQ(OK, rv);
5085}
5086
5087TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425088 HttpRequestInfo request;
5089 request.method = "GET";
5090 request.url = GURL("http://www.google.com/");
5091 request.load_flags = LOAD_BYPASS_CACHE;
5092
[email protected]cb9bf6ca2011-01-28 13:15:275093 SessionDependencies session_deps;
5094 scoped_ptr<HttpTransaction> trans(
5095 new HttpNetworkTransaction(CreateSession(&session_deps)));
5096
[email protected]1c773ea12009-04-28 19:58:425097 MockWrite data_writes[] = {
5098 MockWrite("GET / HTTP/1.1\r\n"
5099 "Host: www.google.com\r\n"
5100 "Connection: keep-alive\r\n"
5101 "Pragma: no-cache\r\n"
5102 "Cache-Control: no-cache\r\n\r\n"),
5103 };
5104
5105 // Lastly, the server responds with the actual content.
5106 MockRead data_reads[] = {
5107 MockRead("HTTP/1.0 200 OK\r\n"),
5108 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5109 MockRead("Content-Length: 100\r\n\r\n"),
5110 MockRead(false, OK),
5111 };
5112
[email protected]31a2bfe2010-02-09 08:03:395113 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5114 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595115 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425116
5117 TestCompletionCallback callback;
5118
[email protected]5a1d7ca2010-04-28 20:12:275119 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425120 EXPECT_EQ(ERR_IO_PENDING, rv);
5121
5122 rv = callback.WaitForResult();
5123 EXPECT_EQ(OK, rv);
5124}
5125
5126TEST_F(HttpNetworkTransactionTest,
5127 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425128 HttpRequestInfo request;
5129 request.method = "GET";
5130 request.url = GURL("http://www.google.com/");
5131 request.load_flags = LOAD_VALIDATE_CACHE;
5132
[email protected]cb9bf6ca2011-01-28 13:15:275133 SessionDependencies session_deps;
5134 scoped_ptr<HttpTransaction> trans(
5135 new HttpNetworkTransaction(CreateSession(&session_deps)));
5136
[email protected]1c773ea12009-04-28 19:58:425137 MockWrite data_writes[] = {
5138 MockWrite("GET / HTTP/1.1\r\n"
5139 "Host: www.google.com\r\n"
5140 "Connection: keep-alive\r\n"
5141 "Cache-Control: max-age=0\r\n\r\n"),
5142 };
5143
5144 // Lastly, the server responds with the actual content.
5145 MockRead data_reads[] = {
5146 MockRead("HTTP/1.0 200 OK\r\n"),
5147 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5148 MockRead("Content-Length: 100\r\n\r\n"),
5149 MockRead(false, OK),
5150 };
5151
[email protected]31a2bfe2010-02-09 08:03:395152 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5153 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595154 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425155
5156 TestCompletionCallback callback;
5157
[email protected]5a1d7ca2010-04-28 20:12:275158 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425159 EXPECT_EQ(ERR_IO_PENDING, rv);
5160
5161 rv = callback.WaitForResult();
5162 EXPECT_EQ(OK, rv);
5163}
5164
5165TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425166 HttpRequestInfo request;
5167 request.method = "GET";
5168 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435169 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425170
[email protected]cb9bf6ca2011-01-28 13:15:275171 SessionDependencies session_deps;
5172 scoped_ptr<HttpTransaction> trans(
5173 new HttpNetworkTransaction(CreateSession(&session_deps)));
5174
[email protected]1c773ea12009-04-28 19:58:425175 MockWrite data_writes[] = {
5176 MockWrite("GET / HTTP/1.1\r\n"
5177 "Host: www.google.com\r\n"
5178 "Connection: keep-alive\r\n"
5179 "FooHeader: Bar\r\n\r\n"),
5180 };
5181
5182 // Lastly, the server responds with the actual content.
5183 MockRead data_reads[] = {
5184 MockRead("HTTP/1.0 200 OK\r\n"),
5185 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5186 MockRead("Content-Length: 100\r\n\r\n"),
5187 MockRead(false, OK),
5188 };
5189
[email protected]31a2bfe2010-02-09 08:03:395190 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5191 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595192 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425193
5194 TestCompletionCallback callback;
5195
[email protected]5a1d7ca2010-04-28 20:12:275196 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425197 EXPECT_EQ(ERR_IO_PENDING, rv);
5198
5199 rv = callback.WaitForResult();
5200 EXPECT_EQ(OK, rv);
5201}
5202
[email protected]270c6412010-03-29 22:02:475203TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475204 HttpRequestInfo request;
5205 request.method = "GET";
5206 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435207 request.extra_headers.SetHeader("referer", "www.foo.com");
5208 request.extra_headers.SetHeader("hEllo", "Kitty");
5209 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475210
[email protected]cb9bf6ca2011-01-28 13:15:275211 SessionDependencies session_deps;
5212 scoped_ptr<HttpTransaction> trans(
5213 new HttpNetworkTransaction(CreateSession(&session_deps)));
5214
[email protected]270c6412010-03-29 22:02:475215 MockWrite data_writes[] = {
5216 MockWrite("GET / HTTP/1.1\r\n"
5217 "Host: www.google.com\r\n"
5218 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165219 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475220 "hEllo: Kitty\r\n"
5221 "FoO: bar\r\n\r\n"),
5222 };
5223
5224 // Lastly, the server responds with the actual content.
5225 MockRead data_reads[] = {
5226 MockRead("HTTP/1.0 200 OK\r\n"),
5227 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5228 MockRead("Content-Length: 100\r\n\r\n"),
5229 MockRead(false, OK),
5230 };
5231
5232 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5233 data_writes, arraysize(data_writes));
5234 session_deps.socket_factory.AddSocketDataProvider(&data);
5235
5236 TestCompletionCallback callback;
5237
[email protected]5a1d7ca2010-04-28 20:12:275238 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475239 EXPECT_EQ(ERR_IO_PENDING, rv);
5240
5241 rv = callback.WaitForResult();
5242 EXPECT_EQ(OK, rv);
5243}
5244
[email protected]3cd17242009-06-23 02:59:025245TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275246 HttpRequestInfo request;
5247 request.method = "GET";
5248 request.url = GURL("http://www.google.com/");
5249 request.load_flags = 0;
5250
[email protected]80d6524d2009-08-18 03:58:095251 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005252 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025253
5254 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435255 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025256
[email protected]3cd17242009-06-23 02:59:025257 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5258 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5259
5260 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355261 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025262 MockWrite("GET / HTTP/1.1\r\n"
5263 "Host: www.google.com\r\n"
5264 "Connection: keep-alive\r\n\r\n")
5265 };
5266
5267 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595268 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025269 MockRead("HTTP/1.0 200 OK\r\n"),
5270 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5271 MockRead("Payload"),
5272 MockRead(false, OK)
5273 };
5274
[email protected]31a2bfe2010-02-09 08:03:395275 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5276 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595277 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025278
5279 TestCompletionCallback callback;
5280
[email protected]5a1d7ca2010-04-28 20:12:275281 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025282 EXPECT_EQ(ERR_IO_PENDING, rv);
5283
5284 rv = callback.WaitForResult();
5285 EXPECT_EQ(OK, rv);
5286
5287 const HttpResponseInfo* response = trans->GetResponseInfo();
5288 EXPECT_FALSE(response == NULL);
5289
5290 std::string response_text;
5291 rv = ReadTransaction(trans.get(), &response_text);
5292 EXPECT_EQ(OK, rv);
5293 EXPECT_EQ("Payload", response_text);
5294}
5295
5296TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275297 HttpRequestInfo request;
5298 request.method = "GET";
5299 request.url = GURL("https://www.google.com/");
5300 request.load_flags = 0;
5301
[email protected]80d6524d2009-08-18 03:58:095302 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005303 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025304
5305 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435306 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025307
[email protected]3cd17242009-06-23 02:59:025308 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5309 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5310
5311 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355312 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5313 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025314 MockWrite("GET / HTTP/1.1\r\n"
5315 "Host: www.google.com\r\n"
5316 "Connection: keep-alive\r\n\r\n")
5317 };
5318
5319 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355320 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5321 arraysize(read_buffer)),
5322 MockRead("HTTP/1.0 200 OK\r\n"),
5323 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5324 MockRead("Payload"),
5325 MockRead(false, OK)
5326 };
5327
[email protected]31a2bfe2010-02-09 08:03:395328 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5329 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595330 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355331
[email protected]5ecc992a42009-11-11 01:41:595332 SSLSocketDataProvider ssl(true, OK);
5333 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355334
5335 TestCompletionCallback callback;
5336
[email protected]5a1d7ca2010-04-28 20:12:275337 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355338 EXPECT_EQ(ERR_IO_PENDING, rv);
5339
5340 rv = callback.WaitForResult();
5341 EXPECT_EQ(OK, rv);
5342
5343 const HttpResponseInfo* response = trans->GetResponseInfo();
5344 EXPECT_FALSE(response == NULL);
5345
5346 std::string response_text;
5347 rv = ReadTransaction(trans.get(), &response_text);
5348 EXPECT_EQ(OK, rv);
5349 EXPECT_EQ("Payload", response_text);
5350}
5351
5352TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275353 HttpRequestInfo request;
5354 request.method = "GET";
5355 request.url = GURL("http://www.google.com/");
5356 request.load_flags = 0;
5357
[email protected]80d6524d2009-08-18 03:58:095358 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005359 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355360
5361 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435362 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355363
[email protected]e0c27be2009-07-15 13:09:355364 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5365 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375366 const char kSOCKS5OkRequest[] = {
5367 0x05, // Version
5368 0x01, // Command (CONNECT)
5369 0x00, // Reserved.
5370 0x03, // Address type (DOMAINNAME).
5371 0x0E, // Length of domain (14)
5372 // Domain string:
5373 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5374 0x00, 0x50, // 16-bit port (80)
5375 };
[email protected]e0c27be2009-07-15 13:09:355376 const char kSOCKS5OkResponse[] =
5377 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5378
5379 MockWrite data_writes[] = {
5380 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5381 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5382 MockWrite("GET / HTTP/1.1\r\n"
5383 "Host: www.google.com\r\n"
5384 "Connection: keep-alive\r\n\r\n")
5385 };
5386
5387 MockRead data_reads[] = {
5388 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5389 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5390 MockRead("HTTP/1.0 200 OK\r\n"),
5391 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5392 MockRead("Payload"),
5393 MockRead(false, OK)
5394 };
5395
[email protected]31a2bfe2010-02-09 08:03:395396 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5397 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595398 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355399
5400 TestCompletionCallback callback;
5401
[email protected]5a1d7ca2010-04-28 20:12:275402 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355403 EXPECT_EQ(ERR_IO_PENDING, rv);
5404
5405 rv = callback.WaitForResult();
5406 EXPECT_EQ(OK, rv);
5407
5408 const HttpResponseInfo* response = trans->GetResponseInfo();
5409 EXPECT_FALSE(response == NULL);
5410
5411 std::string response_text;
5412 rv = ReadTransaction(trans.get(), &response_text);
5413 EXPECT_EQ(OK, rv);
5414 EXPECT_EQ("Payload", response_text);
5415}
5416
5417TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275418 HttpRequestInfo request;
5419 request.method = "GET";
5420 request.url = GURL("https://www.google.com/");
5421 request.load_flags = 0;
5422
[email protected]80d6524d2009-08-18 03:58:095423 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005424 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355425
5426 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435427 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355428
[email protected]e0c27be2009-07-15 13:09:355429 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5430 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375431 const unsigned char kSOCKS5OkRequest[] = {
5432 0x05, // Version
5433 0x01, // Command (CONNECT)
5434 0x00, // Reserved.
5435 0x03, // Address type (DOMAINNAME).
5436 0x0E, // Length of domain (14)
5437 // Domain string:
5438 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5439 0x01, 0xBB, // 16-bit port (443)
5440 };
5441
[email protected]e0c27be2009-07-15 13:09:355442 const char kSOCKS5OkResponse[] =
5443 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5444
5445 MockWrite data_writes[] = {
5446 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5447 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5448 arraysize(kSOCKS5OkRequest)),
5449 MockWrite("GET / HTTP/1.1\r\n"
5450 "Host: www.google.com\r\n"
5451 "Connection: keep-alive\r\n\r\n")
5452 };
5453
5454 MockRead data_reads[] = {
5455 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5456 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025457 MockRead("HTTP/1.0 200 OK\r\n"),
5458 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5459 MockRead("Payload"),
5460 MockRead(false, OK)
5461 };
5462
[email protected]31a2bfe2010-02-09 08:03:395463 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5464 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595465 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025466
[email protected]5ecc992a42009-11-11 01:41:595467 SSLSocketDataProvider ssl(true, OK);
5468 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025469
5470 TestCompletionCallback callback;
5471
[email protected]5a1d7ca2010-04-28 20:12:275472 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025473 EXPECT_EQ(ERR_IO_PENDING, rv);
5474
5475 rv = callback.WaitForResult();
5476 EXPECT_EQ(OK, rv);
5477
5478 const HttpResponseInfo* response = trans->GetResponseInfo();
5479 EXPECT_FALSE(response == NULL);
5480
5481 std::string response_text;
5482 rv = ReadTransaction(trans.get(), &response_text);
5483 EXPECT_EQ(OK, rv);
5484 EXPECT_EQ("Payload", response_text);
5485}
5486
[email protected]04e5be32009-06-26 20:00:315487// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065488
5489struct GroupNameTest {
5490 std::string proxy_server;
5491 std::string url;
5492 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185493 bool ssl;
[email protected]2d731a32010-04-29 01:04:065494};
5495
5496scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025497 SessionDependencies* session_deps) {
5498 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065499
5500 HttpAlternateProtocols* alternate_protocols =
5501 session->mutable_alternate_protocols();
5502 alternate_protocols->SetAlternateProtocolFor(
5503 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355504 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065505
5506 return session;
5507}
5508
5509int GroupNameTransactionHelper(
5510 const std::string& url,
5511 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065512 HttpRequestInfo request;
5513 request.method = "GET";
5514 request.url = GURL(url);
5515 request.load_flags = 0;
5516
[email protected]cb9bf6ca2011-01-28 13:15:275517 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5518
[email protected]2d731a32010-04-29 01:04:065519 TestCompletionCallback callback;
5520
5521 // We do not complete this request, the dtor will clean the transaction up.
5522 return trans->Start(&request, &callback, BoundNetLog());
5523}
5524
5525TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5526 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315527 {
[email protected]2d731a32010-04-29 01:04:065528 "", // unused
[email protected]04e5be32009-06-26 20:00:315529 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545530 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185531 false,
[email protected]2ff8b312010-04-26 22:20:545532 },
5533 {
[email protected]2d731a32010-04-29 01:04:065534 "", // unused
[email protected]2ff8b312010-04-26 22:20:545535 "http://[2001:1418:13:1::25]/direct",
5536 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185537 false,
[email protected]04e5be32009-06-26 20:00:315538 },
[email protected]04e5be32009-06-26 20:00:315539
5540 // SSL Tests
5541 {
[email protected]2d731a32010-04-29 01:04:065542 "", // unused
[email protected]04e5be32009-06-26 20:00:315543 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025544 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185545 true,
[email protected]04e5be32009-06-26 20:00:315546 },
5547 {
[email protected]2d731a32010-04-29 01:04:065548 "", // unused
5549 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025550 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185551 true,
[email protected]04e5be32009-06-26 20:00:315552 },
5553 {
[email protected]2d731a32010-04-29 01:04:065554 "", // unused
[email protected]2ff8b312010-04-26 22:20:545555 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025556 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185557 true,
[email protected]2ff8b312010-04-26 22:20:545558 },
[email protected]2d731a32010-04-29 01:04:065559 };
[email protected]2ff8b312010-04-26 22:20:545560
[email protected]8e6441ca2010-08-19 05:56:385561 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065562
5563 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025564 SessionDependencies session_deps(
5565 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065566 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025567 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065568
5569 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285570 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5571 new CaptureGroupNameTransportSocketPool(NULL, NULL);
5572 peer.SetTransportSocketPool(transport_conn_pool);
[email protected]2431756e2010-09-29 20:26:135573 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345574 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185575 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065576
5577 EXPECT_EQ(ERR_IO_PENDING,
5578 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185579 if (tests[i].ssl)
5580 EXPECT_EQ(tests[i].expected_group_name,
5581 ssl_conn_pool->last_group_name_received());
5582 else
5583 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285584 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065585 }
5586
[email protected]8e6441ca2010-08-19 05:56:385587 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065588}
5589
5590TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5591 const GroupNameTest tests[] = {
5592 {
5593 "http_proxy",
5594 "http://www.google.com/http_proxy_normal",
5595 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185596 false,
[email protected]2d731a32010-04-29 01:04:065597 },
5598
5599 // SSL Tests
5600 {
5601 "http_proxy",
5602 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025603 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185604 true,
[email protected]2d731a32010-04-29 01:04:065605 },
[email protected]af3490e2010-10-16 21:02:295606
[email protected]9faeded92010-04-29 20:03:055607 {
5608 "http_proxy",
5609 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025610 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185611 true,
[email protected]9faeded92010-04-29 20:03:055612 },
[email protected]2d731a32010-04-29 01:04:065613 };
5614
[email protected]8e6441ca2010-08-19 05:56:385615 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065616
5617 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025618 SessionDependencies session_deps(
5619 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065620 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025621 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065622
5623 HttpNetworkSessionPeer peer(session);
5624
[email protected]e60e47a2010-07-14 03:37:185625 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135626 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345627 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185628 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135629 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345630 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185631 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065632
5633 EXPECT_EQ(ERR_IO_PENDING,
5634 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185635 if (tests[i].ssl)
5636 EXPECT_EQ(tests[i].expected_group_name,
5637 ssl_conn_pool->last_group_name_received());
5638 else
5639 EXPECT_EQ(tests[i].expected_group_name,
5640 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065641 }
5642
[email protected]8e6441ca2010-08-19 05:56:385643 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065644}
5645
5646TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5647 const GroupNameTest tests[] = {
5648 {
5649 "socks4://socks_proxy:1080",
5650 "http://www.google.com/socks4_direct",
5651 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185652 false,
[email protected]2d731a32010-04-29 01:04:065653 },
5654 {
5655 "socks5://socks_proxy:1080",
5656 "http://www.google.com/socks5_direct",
5657 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185658 false,
[email protected]2d731a32010-04-29 01:04:065659 },
5660
5661 // SSL Tests
5662 {
5663 "socks4://socks_proxy:1080",
5664 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025665 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185666 true,
[email protected]2d731a32010-04-29 01:04:065667 },
5668 {
5669 "socks5://socks_proxy:1080",
5670 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025671 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185672 true,
[email protected]2d731a32010-04-29 01:04:065673 },
[email protected]af3490e2010-10-16 21:02:295674
[email protected]9faeded92010-04-29 20:03:055675 {
5676 "socks4://socks_proxy:1080",
5677 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025678 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185679 true,
[email protected]9faeded92010-04-29 20:03:055680 },
[email protected]04e5be32009-06-26 20:00:315681 };
5682
[email protected]8e6441ca2010-08-19 05:56:385683 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545684
[email protected]04e5be32009-06-26 20:00:315685 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025686 SessionDependencies session_deps(
5687 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065688 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025689 SetupSessionForGroupNameTests(&session_deps));
5690
[email protected]2d731a32010-04-29 01:04:065691 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315692
[email protected]e60e47a2010-07-14 03:37:185693 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135694 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345695 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185696 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135697 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345698 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185699 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315700
[email protected]5695b8c2009-09-30 21:36:435701 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315702
[email protected]2d731a32010-04-29 01:04:065703 EXPECT_EQ(ERR_IO_PENDING,
5704 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185705 if (tests[i].ssl)
5706 EXPECT_EQ(tests[i].expected_group_name,
5707 ssl_conn_pool->last_group_name_received());
5708 else
5709 EXPECT_EQ(tests[i].expected_group_name,
5710 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315711 }
[email protected]2ff8b312010-04-26 22:20:545712
[email protected]8e6441ca2010-08-19 05:56:385713 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315714}
5715
[email protected]9172a982009-06-06 00:30:255716TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275717 HttpRequestInfo request;
5718 request.method = "GET";
5719 request.url = GURL("http://www.google.com/");
5720
[email protected]5c6a17e2009-06-10 00:54:545721 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005722 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325723
[email protected]69719062010-01-05 20:09:215724 // This simulates failure resolving all hostnames; that means we will fail
5725 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325726 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5727
[email protected]9172a982009-06-06 00:30:255728 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435729 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255730
[email protected]9172a982009-06-06 00:30:255731 TestCompletionCallback callback;
5732
[email protected]5a1d7ca2010-04-28 20:12:275733 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255734 EXPECT_EQ(ERR_IO_PENDING, rv);
5735
[email protected]9172a982009-06-06 00:30:255736 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015737 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255738}
5739
[email protected]f3e6c1e2009-06-15 20:52:125740// Host resolution observer used by
5741// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5742// resovle requests are issued with a referrer of |expected_referrer|.
5743class ResolutionReferrerObserver : public HostResolver::Observer {
5744 public:
5745 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5746 : expected_referrer_(expected_referrer),
5747 called_start_with_referrer_(false),
5748 called_finish_with_referrer_(false) {
5749 }
5750
5751 virtual void OnStartResolution(int id,
5752 const HostResolver::RequestInfo& info) {
5753 if (info.referrer() == expected_referrer_)
5754 called_start_with_referrer_ = true;
5755 }
5756
5757 virtual void OnFinishResolutionWithStatus(
5758 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5759 if (info.referrer() == expected_referrer_)
5760 called_finish_with_referrer_ = true;
5761 }
5762
[email protected]eb255d32009-06-17 02:11:035763 virtual void OnCancelResolution(int id,
5764 const HostResolver::RequestInfo& info ) {
5765 FAIL() << "Should not be cancelling any requests!";
5766 }
5767
[email protected]f3e6c1e2009-06-15 20:52:125768 bool did_complete_with_expected_referrer() const {
5769 return called_start_with_referrer_ && called_finish_with_referrer_;
5770 }
5771
5772 private:
5773 GURL expected_referrer_;
5774 bool called_start_with_referrer_;
5775 bool called_finish_with_referrer_;
5776
5777 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5778};
5779
5780// Make sure that when HostResolver::Resolve() is invoked, it passes through
5781// the "referrer". This is depended on by the DNS prefetch observer.
5782TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5783 GURL referrer = GURL("http://expected-referrer/");
5784 EXPECT_TRUE(referrer.is_valid());
5785 ResolutionReferrerObserver resolution_observer(referrer);
5786
[email protected]cb9bf6ca2011-01-28 13:15:275787 // Issue a request, containing an HTTP referrer.
5788 HttpRequestInfo request;
5789 request.method = "GET";
[email protected]cb9bf6ca2011-01-28 13:15:275790 request.url = GURL("http://www.google.com/");
[email protected]c10450102011-06-27 09:06:165791 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5792 referrer.spec());
[email protected]cb9bf6ca2011-01-28 13:15:275793
[email protected]f3e6c1e2009-06-15 20:52:125794 SessionDependencies session_deps;
5795 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435796 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125797
5798 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145799 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125800
5801 // Connect up a mock socket which will fail when reading.
5802 MockRead data_reads[] = {
5803 MockRead(false, ERR_FAILED),
5804 };
[email protected]31a2bfe2010-02-09 08:03:395805 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595806 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125807
[email protected]f3e6c1e2009-06-15 20:52:125808 // Run the request until it fails reading from the socket.
5809 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275810 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125811 EXPECT_EQ(ERR_IO_PENDING, rv);
5812 rv = callback.WaitForResult();
5813 EXPECT_EQ(ERR_FAILED, rv);
5814
5815 // Check that the host resolution observer saw |referrer|.
5816 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5817}
5818
[email protected]685af592010-05-11 19:31:245819// Base test to make sure that when the load flags for a request specify to
5820// bypass the cache, the DNS cache is not used.
5821void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275822 // Issue a request, asking to bypass the cache(s).
5823 HttpRequestInfo request;
5824 request.method = "GET";
5825 request.load_flags = load_flags;
5826 request.url = GURL("http://www.google.com/");
5827
[email protected]3b9cca42009-06-16 01:08:285828 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325829
[email protected]a2c2fb92009-07-18 07:31:045830 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545831 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325832
[email protected]3b9cca42009-06-16 01:08:285833 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435834 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285835
5836 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5837 // a synchronous lookup.)
5838 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145839 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105840 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275841 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285842 EXPECT_EQ(OK, rv);
5843
5844 // Verify that it was added to host cache, by doing a subsequent async lookup
5845 // and confirming it completes synchronously.
5846 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465847 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105848 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275849 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325850 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285851
5852 // Inject a failure the next time that "www.google.com" is resolved. This way
5853 // we can tell if the next lookup hit the cache, or the "network".
5854 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325855 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285856
5857 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5858 // first read -- this won't be reached as the host resolution will fail first.
5859 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395860 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595861 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285862
[email protected]3b9cca42009-06-16 01:08:285863 // Run the request.
5864 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275865 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285866 ASSERT_EQ(ERR_IO_PENDING, rv);
5867 rv = callback.WaitForResult();
5868
5869 // If we bypassed the cache, we would have gotten a failure while resolving
5870 // "www.google.com".
5871 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5872}
5873
[email protected]685af592010-05-11 19:31:245874// There are multiple load flags that should trigger the host cache bypass.
5875// Test each in isolation:
5876TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5877 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5878}
5879
5880TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5881 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5882}
5883
5884TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5885 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5886}
5887
[email protected]0877e3d2009-10-17 22:29:575888// Make sure we can handle an error when writing the request.
5889TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5890 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275891 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575892
5893 HttpRequestInfo request;
5894 request.method = "GET";
5895 request.url = GURL("http://www.foo.com/");
5896 request.load_flags = 0;
5897
5898 MockWrite write_failure[] = {
5899 MockWrite(true, ERR_CONNECTION_RESET),
5900 };
[email protected]31a2bfe2010-02-09 08:03:395901 StaticSocketDataProvider data(NULL, 0,
5902 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595903 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575904
5905 TestCompletionCallback callback;
5906
5907 scoped_ptr<HttpTransaction> trans(
5908 new HttpNetworkTransaction(CreateSession(&session_deps)));
5909
[email protected]5a1d7ca2010-04-28 20:12:275910 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575911 EXPECT_EQ(ERR_IO_PENDING, rv);
5912
5913 rv = callback.WaitForResult();
5914 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5915}
5916
5917// Check that a connection closed after the start of the headers finishes ok.
5918TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5919 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275920 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575921
5922 HttpRequestInfo request;
5923 request.method = "GET";
5924 request.url = GURL("http://www.foo.com/");
5925 request.load_flags = 0;
5926
5927 MockRead data_reads[] = {
5928 MockRead("HTTP/1."),
5929 MockRead(false, OK),
5930 };
5931
[email protected]31a2bfe2010-02-09 08:03:395932 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595933 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575934
5935 TestCompletionCallback callback;
5936
5937 scoped_ptr<HttpTransaction> trans(
5938 new HttpNetworkTransaction(CreateSession(&session_deps)));
5939
[email protected]5a1d7ca2010-04-28 20:12:275940 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575941 EXPECT_EQ(ERR_IO_PENDING, rv);
5942
5943 rv = callback.WaitForResult();
5944 EXPECT_EQ(OK, rv);
5945
5946 const HttpResponseInfo* response = trans->GetResponseInfo();
5947 EXPECT_TRUE(response != NULL);
5948
5949 EXPECT_TRUE(response->headers != NULL);
5950 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5951
5952 std::string response_data;
5953 rv = ReadTransaction(trans.get(), &response_data);
5954 EXPECT_EQ(OK, rv);
5955 EXPECT_EQ("", response_data);
5956}
5957
5958// Make sure that a dropped connection while draining the body for auth
5959// restart does the right thing.
5960TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5961 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275962 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575963
5964 HttpRequestInfo request;
5965 request.method = "GET";
5966 request.url = GURL("http://www.google.com/");
5967 request.load_flags = 0;
5968
5969 MockWrite data_writes1[] = {
5970 MockWrite("GET / HTTP/1.1\r\n"
5971 "Host: www.google.com\r\n"
5972 "Connection: keep-alive\r\n\r\n"),
5973 };
5974
5975 MockRead data_reads1[] = {
5976 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5977 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5978 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5979 MockRead("Content-Length: 14\r\n\r\n"),
5980 MockRead("Unauth"),
5981 MockRead(true, ERR_CONNECTION_RESET),
5982 };
5983
[email protected]31a2bfe2010-02-09 08:03:395984 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5985 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595986 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575987
5988 // After calling trans->RestartWithAuth(), this is the request we should
5989 // be issuing -- the final header line contains the credentials.
5990 MockWrite data_writes2[] = {
5991 MockWrite("GET / HTTP/1.1\r\n"
5992 "Host: www.google.com\r\n"
5993 "Connection: keep-alive\r\n"
5994 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5995 };
5996
5997 // Lastly, the server responds with the actual content.
5998 MockRead data_reads2[] = {
5999 MockRead("HTTP/1.1 200 OK\r\n"),
6000 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6001 MockRead("Content-Length: 100\r\n\r\n"),
6002 MockRead(false, OK),
6003 };
6004
[email protected]31a2bfe2010-02-09 08:03:396005 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6006 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:596007 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:576008
6009 TestCompletionCallback callback1;
6010
[email protected]0b0bf032010-09-21 18:08:506011 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6012
[email protected]5a1d7ca2010-04-28 20:12:276013 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576014 EXPECT_EQ(ERR_IO_PENDING, rv);
6015
6016 rv = callback1.WaitForResult();
6017 EXPECT_EQ(OK, rv);
6018
6019 const HttpResponseInfo* response = trans->GetResponseInfo();
6020 EXPECT_FALSE(response == NULL);
6021
6022 // The password prompt info should have been set in response->auth_challenge.
6023 EXPECT_FALSE(response->auth_challenge.get() == NULL);
6024
6025 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6026 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6027 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6028
6029 TestCompletionCallback callback2;
6030
[email protected]13c8a092010-07-29 06:15:446031 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:576032 EXPECT_EQ(ERR_IO_PENDING, rv);
6033
6034 rv = callback2.WaitForResult();
6035 EXPECT_EQ(OK, rv);
6036
6037 response = trans->GetResponseInfo();
6038 EXPECT_FALSE(response == NULL);
6039 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6040 EXPECT_EQ(100, response->headers->GetContentLength());
6041}
6042
6043// Test HTTPS connections going through a proxy that sends extra data.
6044TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006045 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576046
6047 HttpRequestInfo request;
6048 request.method = "GET";
6049 request.url = GURL("https://www.google.com/");
6050 request.load_flags = 0;
6051
6052 MockRead proxy_reads[] = {
6053 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6054 MockRead(false, OK)
6055 };
6056
[email protected]31a2bfe2010-02-09 08:03:396057 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596058 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576059
[email protected]5ecc992a42009-11-11 01:41:596060 session_deps.socket_factory.AddSocketDataProvider(&data);
6061 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576062
6063 TestCompletionCallback callback;
6064
6065 session_deps.socket_factory.ResetNextMockIndexes();
6066
6067 scoped_ptr<HttpTransaction> trans(
6068 new HttpNetworkTransaction(CreateSession(&session_deps)));
6069
[email protected]5a1d7ca2010-04-28 20:12:276070 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576071 EXPECT_EQ(ERR_IO_PENDING, rv);
6072
6073 rv = callback.WaitForResult();
6074 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6075}
6076
[email protected]e22e1362009-11-23 21:31:126077TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466078 HttpRequestInfo request;
6079 request.method = "GET";
6080 request.url = GURL("http://www.google.com/");
6081 request.load_flags = 0;
6082
[email protected]cb9bf6ca2011-01-28 13:15:276083 SessionDependencies session_deps;
6084 scoped_ptr<HttpTransaction> trans(
6085 new HttpNetworkTransaction(CreateSession(&session_deps)));
6086
[email protected]e22e1362009-11-23 21:31:126087 MockRead data_reads[] = {
6088 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6089 MockRead(false, OK),
6090 };
[email protected]9492e4a2010-02-24 00:58:466091
6092 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6093 session_deps.socket_factory.AddSocketDataProvider(&data);
6094
6095 TestCompletionCallback callback;
6096
[email protected]5a1d7ca2010-04-28 20:12:276097 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466098 EXPECT_EQ(ERR_IO_PENDING, rv);
6099
6100 EXPECT_EQ(OK, callback.WaitForResult());
6101
6102 const HttpResponseInfo* response = trans->GetResponseInfo();
6103 EXPECT_TRUE(response != NULL);
6104
6105 EXPECT_TRUE(response->headers != NULL);
6106 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6107
6108 std::string response_data;
6109 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f0e2bf42011-07-22 21:21:446110 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126111}
6112
[email protected]95d88ffe2010-02-04 21:25:336113TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336114 HttpRequestInfo request;
6115 request.method = "POST";
6116 request.url = GURL("http://www.google.com/upload");
6117 request.upload_data = new UploadData;
6118 request.load_flags = 0;
6119
[email protected]cb9bf6ca2011-01-28 13:15:276120 SessionDependencies session_deps;
6121 scoped_ptr<HttpTransaction> trans(
6122 new HttpNetworkTransaction(CreateSession(&session_deps)));
6123
[email protected]95d88ffe2010-02-04 21:25:336124 FilePath temp_file_path;
6125 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6126 const uint64 kFakeSize = 100000; // file is actually blank
6127
6128 std::vector<UploadData::Element> elements;
6129 UploadData::Element element;
6130 element.SetToFilePath(temp_file_path);
6131 element.SetContentLength(kFakeSize);
6132 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536133 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336134 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6135
6136 MockRead data_reads[] = {
6137 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6138 MockRead("hello world"),
6139 MockRead(false, OK),
6140 };
[email protected]31a2bfe2010-02-09 08:03:396141 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336142 session_deps.socket_factory.AddSocketDataProvider(&data);
6143
6144 TestCompletionCallback callback;
6145
[email protected]5a1d7ca2010-04-28 20:12:276146 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336147 EXPECT_EQ(ERR_IO_PENDING, rv);
6148
6149 rv = callback.WaitForResult();
6150 EXPECT_EQ(OK, rv);
6151
6152 const HttpResponseInfo* response = trans->GetResponseInfo();
6153 EXPECT_TRUE(response != NULL);
6154
6155 EXPECT_TRUE(response->headers != NULL);
6156 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6157
6158 std::string response_data;
6159 rv = ReadTransaction(trans.get(), &response_data);
6160 EXPECT_EQ(OK, rv);
6161 EXPECT_EQ("hello world", response_data);
6162
6163 file_util::Delete(temp_file_path, false);
6164}
6165
[email protected]6624b4622010-03-29 19:58:366166TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276167 HttpRequestInfo request;
6168 request.method = "POST";
6169 request.url = GURL("http://www.google.com/upload");
6170 request.upload_data = new UploadData;
6171 request.load_flags = 0;
6172
[email protected]6624b4622010-03-29 19:58:366173 // If we try to upload an unreadable file, the network stack should report
6174 // the file size as zero and upload zero bytes for that file.
6175 SessionDependencies session_deps;
6176 scoped_ptr<HttpTransaction> trans(
6177 new HttpNetworkTransaction(CreateSession(&session_deps)));
6178
6179 FilePath temp_file;
6180 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6181 std::string temp_file_content("Unreadable file.");
6182 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6183 temp_file_content.length()));
6184 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6185
[email protected]6624b4622010-03-29 19:58:366186 std::vector<UploadData::Element> elements;
6187 UploadData::Element element;
6188 element.SetToFilePath(temp_file);
6189 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536190 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366191
6192 MockRead data_reads[] = {
6193 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6194 MockRead(false, OK),
6195 };
6196 MockWrite data_writes[] = {
6197 MockWrite("POST /upload HTTP/1.1\r\n"
6198 "Host: www.google.com\r\n"
6199 "Connection: keep-alive\r\n"
6200 "Content-Length: 0\r\n\r\n"),
6201 MockWrite(false, OK),
6202 };
6203 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6204 arraysize(data_writes));
6205 session_deps.socket_factory.AddSocketDataProvider(&data);
6206
6207 TestCompletionCallback callback;
6208
[email protected]5a1d7ca2010-04-28 20:12:276209 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366210 EXPECT_EQ(ERR_IO_PENDING, rv);
6211
6212 rv = callback.WaitForResult();
6213 EXPECT_EQ(OK, rv);
6214
6215 const HttpResponseInfo* response = trans->GetResponseInfo();
6216 EXPECT_TRUE(response != NULL);
6217 EXPECT_TRUE(response->headers != NULL);
6218 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6219
6220 file_util::Delete(temp_file, false);
6221}
6222
6223TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276224 HttpRequestInfo request;
6225 request.method = "POST";
6226 request.url = GURL("http://www.google.com/upload");
6227 request.upload_data = new UploadData;
6228 request.load_flags = 0;
6229
[email protected]6624b4622010-03-29 19:58:366230 SessionDependencies session_deps;
6231 scoped_ptr<HttpTransaction> trans(
6232 new HttpNetworkTransaction(CreateSession(&session_deps)));
6233
6234 FilePath temp_file;
6235 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6236 std::string temp_file_contents("Unreadable file.");
6237 std::string unreadable_contents(temp_file_contents.length(), '\0');
6238 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6239 temp_file_contents.length()));
6240
[email protected]6624b4622010-03-29 19:58:366241 std::vector<UploadData::Element> elements;
6242 UploadData::Element element;
6243 element.SetToFilePath(temp_file);
6244 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536245 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366246
6247 MockRead data_reads[] = {
6248 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6249 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6250 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6251
6252 MockRead("HTTP/1.1 200 OK\r\n"),
6253 MockRead("Content-Length: 0\r\n\r\n"),
6254 MockRead(false, OK),
6255 };
6256 MockWrite data_writes[] = {
6257 MockWrite("POST /upload HTTP/1.1\r\n"
6258 "Host: www.google.com\r\n"
6259 "Connection: keep-alive\r\n"
6260 "Content-Length: 16\r\n\r\n"),
6261 MockWrite(false, temp_file_contents.c_str()),
6262
6263 MockWrite("POST /upload HTTP/1.1\r\n"
6264 "Host: www.google.com\r\n"
6265 "Connection: keep-alive\r\n"
6266 "Content-Length: 16\r\n"
6267 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6268 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6269 MockWrite(false, OK),
6270 };
6271 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6272 arraysize(data_writes));
6273 session_deps.socket_factory.AddSocketDataProvider(&data);
6274
6275 TestCompletionCallback callback1;
6276
[email protected]5a1d7ca2010-04-28 20:12:276277 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366278 EXPECT_EQ(ERR_IO_PENDING, rv);
6279
6280 rv = callback1.WaitForResult();
6281 EXPECT_EQ(OK, rv);
6282
6283 const HttpResponseInfo* response = trans->GetResponseInfo();
6284 EXPECT_TRUE(response != NULL);
6285 EXPECT_TRUE(response->headers != NULL);
6286 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6287
6288 // The password prompt info should have been set in response->auth_challenge.
6289 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6290 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6291 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6292 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6293
6294 // Now make the file unreadable and try again.
6295 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6296
6297 TestCompletionCallback callback2;
6298
[email protected]13c8a092010-07-29 06:15:446299 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366300 EXPECT_EQ(ERR_IO_PENDING, rv);
6301
6302 rv = callback2.WaitForResult();
6303 EXPECT_EQ(OK, rv);
6304
6305 response = trans->GetResponseInfo();
6306 EXPECT_TRUE(response != NULL);
6307 EXPECT_TRUE(response->headers != NULL);
6308 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6309 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6310
6311 file_util::Delete(temp_file, false);
6312}
6313
[email protected]aeefc9e82010-02-19 16:18:276314// Tests that changes to Auth realms are treated like auth rejections.
6315TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6316 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276317
6318 HttpRequestInfo request;
6319 request.method = "GET";
6320 request.url = GURL("http://www.google.com/");
6321 request.load_flags = 0;
6322
6323 // First transaction will request a resource and receive a Basic challenge
6324 // with realm="first_realm".
6325 MockWrite data_writes1[] = {
6326 MockWrite("GET / HTTP/1.1\r\n"
6327 "Host: www.google.com\r\n"
6328 "Connection: keep-alive\r\n"
6329 "\r\n"),
6330 };
6331 MockRead data_reads1[] = {
6332 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6333 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6334 "\r\n"),
6335 };
6336
6337 // After calling trans->RestartWithAuth(), provide an Authentication header
6338 // for first_realm. The server will reject and provide a challenge with
6339 // second_realm.
6340 MockWrite data_writes2[] = {
6341 MockWrite("GET / HTTP/1.1\r\n"
6342 "Host: www.google.com\r\n"
6343 "Connection: keep-alive\r\n"
6344 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6345 "\r\n"),
6346 };
6347 MockRead data_reads2[] = {
6348 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6349 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6350 "\r\n"),
6351 };
6352
6353 // This again fails, and goes back to first_realm. Make sure that the
6354 // entry is removed from cache.
6355 MockWrite data_writes3[] = {
6356 MockWrite("GET / HTTP/1.1\r\n"
6357 "Host: www.google.com\r\n"
6358 "Connection: keep-alive\r\n"
6359 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6360 "\r\n"),
6361 };
6362 MockRead data_reads3[] = {
6363 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6364 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6365 "\r\n"),
6366 };
6367
6368 // Try one last time (with the correct password) and get the resource.
6369 MockWrite data_writes4[] = {
6370 MockWrite("GET / HTTP/1.1\r\n"
6371 "Host: www.google.com\r\n"
6372 "Connection: keep-alive\r\n"
6373 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6374 "\r\n"),
6375 };
6376 MockRead data_reads4[] = {
6377 MockRead("HTTP/1.1 200 OK\r\n"
6378 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506379 "Content-Length: 5\r\n"
6380 "\r\n"
6381 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276382 };
6383
6384 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6385 data_writes1, arraysize(data_writes1));
6386 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6387 data_writes2, arraysize(data_writes2));
6388 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6389 data_writes3, arraysize(data_writes3));
6390 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6391 data_writes4, arraysize(data_writes4));
6392 session_deps.socket_factory.AddSocketDataProvider(&data1);
6393 session_deps.socket_factory.AddSocketDataProvider(&data2);
6394 session_deps.socket_factory.AddSocketDataProvider(&data3);
6395 session_deps.socket_factory.AddSocketDataProvider(&data4);
6396
6397 TestCompletionCallback callback1;
6398
[email protected]0b0bf032010-09-21 18:08:506399 scoped_ptr<HttpTransaction> trans(
6400 new HttpNetworkTransaction(CreateSession(&session_deps)));
6401
[email protected]aeefc9e82010-02-19 16:18:276402 // Issue the first request with Authorize headers. There should be a
6403 // password prompt for first_realm waiting to be filled in after the
6404 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276405 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276406 EXPECT_EQ(ERR_IO_PENDING, rv);
6407 rv = callback1.WaitForResult();
6408 EXPECT_EQ(OK, rv);
6409 const HttpResponseInfo* response = trans->GetResponseInfo();
6410 ASSERT_FALSE(response == NULL);
6411 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6412 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6413 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6414 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6415
6416 // Issue the second request with an incorrect password. There should be a
6417 // password prompt for second_realm waiting to be filled in after the
6418 // transaction completes.
6419 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446420 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276421 EXPECT_EQ(ERR_IO_PENDING, rv);
6422 rv = callback2.WaitForResult();
6423 EXPECT_EQ(OK, rv);
6424 response = trans->GetResponseInfo();
6425 ASSERT_FALSE(response == NULL);
6426 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6427 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6428 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6429 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6430
6431 // Issue the third request with another incorrect password. There should be
6432 // a password prompt for first_realm waiting to be filled in. If the password
6433 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6434 // first_realm was not correctly removed.
6435 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446436 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276437 EXPECT_EQ(ERR_IO_PENDING, rv);
6438 rv = callback3.WaitForResult();
6439 EXPECT_EQ(OK, rv);
6440 response = trans->GetResponseInfo();
6441 ASSERT_FALSE(response == NULL);
6442 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6443 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6444 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6445 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6446
6447 // Issue the fourth request with the correct password and username.
6448 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446449 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276450 EXPECT_EQ(ERR_IO_PENDING, rv);
6451 rv = callback4.WaitForResult();
6452 EXPECT_EQ(OK, rv);
6453 response = trans->GetResponseInfo();
6454 ASSERT_FALSE(response == NULL);
6455 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6456}
6457
[email protected]564b4912010-03-09 16:30:426458TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386459 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6460 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426461
[email protected]564b4912010-03-09 16:30:426462 SessionDependencies session_deps;
6463
6464 MockRead data_reads[] = {
6465 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356466 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426467 MockRead("hello world"),
6468 MockRead(false, OK),
6469 };
6470
6471 HttpRequestInfo request;
6472 request.method = "GET";
6473 request.url = GURL("http://www.google.com/");
6474 request.load_flags = 0;
6475
6476 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6477
6478 session_deps.socket_factory.AddSocketDataProvider(&data);
6479
6480 TestCompletionCallback callback;
6481
6482 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6483 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6484
[email protected]5a1d7ca2010-04-28 20:12:276485 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426486 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536487
[email protected]2fbaecf22010-07-22 22:20:356488 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426489 const HttpAlternateProtocols& alternate_protocols =
6490 session->alternate_protocols();
6491 EXPECT_FALSE(
6492 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6493
6494 EXPECT_EQ(OK, callback.WaitForResult());
6495
6496 const HttpResponseInfo* response = trans->GetResponseInfo();
6497 ASSERT_TRUE(response != NULL);
6498 ASSERT_TRUE(response->headers != NULL);
6499 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536500 EXPECT_FALSE(response->was_fetched_via_spdy);
6501 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426502
6503 std::string response_data;
6504 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6505 EXPECT_EQ("hello world", response_data);
6506
6507 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6508 const HttpAlternateProtocols::PortProtocolPair alternate =
6509 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6510 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6511 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356512 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426513 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426514
[email protected]8e6441ca2010-08-19 05:56:386515 HttpStreamFactory::set_use_alternate_protocols(false);
6516 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426517}
6518
[email protected]8b95ed62011-03-18 18:12:036519TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386520 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426521 SessionDependencies session_deps;
6522
6523 HttpRequestInfo request;
6524 request.method = "GET";
6525 request.url = GURL("http://www.google.com/");
6526 request.load_flags = 0;
6527
6528 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6529 StaticSocketDataProvider first_data;
6530 first_data.set_connect_data(mock_connect);
6531 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6532
6533 MockRead data_reads[] = {
6534 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6535 MockRead("hello world"),
6536 MockRead(true, OK),
6537 };
6538 StaticSocketDataProvider second_data(
6539 data_reads, arraysize(data_reads), NULL, 0);
6540 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6541
[email protected]564b4912010-03-09 16:30:426542 TestCompletionCallback callback;
6543
6544 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6545
[email protected]2fbaecf22010-07-22 22:20:356546 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426547 HttpAlternateProtocols* alternate_protocols =
6548 session->mutable_alternate_protocols();
6549 alternate_protocols->SetAlternateProtocolFor(
6550 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356551 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426552
6553 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6554
[email protected]5a1d7ca2010-04-28 20:12:276555 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426556 EXPECT_EQ(ERR_IO_PENDING, rv);
6557 EXPECT_EQ(OK, callback.WaitForResult());
6558
6559 const HttpResponseInfo* response = trans->GetResponseInfo();
6560 ASSERT_TRUE(response != NULL);
6561 ASSERT_TRUE(response->headers != NULL);
6562 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6563
6564 std::string response_data;
6565 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6566 EXPECT_EQ("hello world", response_data);
6567
6568 ASSERT_TRUE(
6569 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6570 const HttpAlternateProtocols::PortProtocolPair alternate =
6571 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6572 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386573 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426574}
6575
[email protected]2ff8b312010-04-26 22:20:546576TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386577 HttpStreamFactory::set_use_alternate_protocols(true);
6578 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546579 SessionDependencies session_deps;
6580
6581 HttpRequestInfo request;
6582 request.method = "GET";
6583 request.url = GURL("http://www.google.com/");
6584 request.load_flags = 0;
6585
6586 MockRead data_reads[] = {
6587 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356588 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546589 MockRead("hello world"),
6590 MockRead(true, OK),
6591 };
6592
6593 StaticSocketDataProvider first_transaction(
6594 data_reads, arraysize(data_reads), NULL, 0);
6595 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6596
6597 SSLSocketDataProvider ssl(true, OK);
6598 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356599 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536600 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546601 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6602
[email protected]2bd93022010-07-17 00:58:446603 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136604 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546605
[email protected]2bd93022010-07-17 00:58:446606 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6607 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546608 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136609 CreateMockRead(*resp),
6610 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546611 MockRead(true, 0, 0),
6612 };
6613
6614 scoped_refptr<DelayedSocketData> spdy_data(
6615 new DelayedSocketData(
6616 1, // wait for one write to finish before reading.
6617 spdy_reads, arraysize(spdy_reads),
6618 spdy_writes, arraysize(spdy_writes)));
6619 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6620
[email protected]2d6728692011-03-12 01:39:556621 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6622 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6623 NULL, 0, NULL, 0);
6624 hanging_non_alternate_protocol_socket.set_connect_data(
6625 never_finishing_connect);
6626 session_deps.socket_factory.AddSocketDataProvider(
6627 &hanging_non_alternate_protocol_socket);
6628
[email protected]2ff8b312010-04-26 22:20:546629 TestCompletionCallback callback;
6630
6631 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6632 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6633
[email protected]5a1d7ca2010-04-28 20:12:276634 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546635 EXPECT_EQ(ERR_IO_PENDING, rv);
6636 EXPECT_EQ(OK, callback.WaitForResult());
6637
6638 const HttpResponseInfo* response = trans->GetResponseInfo();
6639 ASSERT_TRUE(response != NULL);
6640 ASSERT_TRUE(response->headers != NULL);
6641 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6642
6643 std::string response_data;
6644 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6645 EXPECT_EQ("hello world", response_data);
6646
6647 trans.reset(new HttpNetworkTransaction(session));
6648
[email protected]5a1d7ca2010-04-28 20:12:276649 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546650 EXPECT_EQ(ERR_IO_PENDING, rv);
6651 EXPECT_EQ(OK, callback.WaitForResult());
6652
6653 response = trans->GetResponseInfo();
6654 ASSERT_TRUE(response != NULL);
6655 ASSERT_TRUE(response->headers != NULL);
6656 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536657 EXPECT_TRUE(response->was_fetched_via_spdy);
6658 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546659
6660 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6661 EXPECT_EQ("hello!", response_data);
6662
[email protected]8e6441ca2010-08-19 05:56:386663 HttpStreamFactory::set_next_protos("");
6664 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546665}
6666
[email protected]2d6728692011-03-12 01:39:556667TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6668 HttpStreamFactory::set_use_alternate_protocols(true);
6669 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6670 SessionDependencies session_deps;
6671
6672 HttpRequestInfo request;
6673 request.method = "GET";
6674 request.url = GURL("http://www.google.com/");
6675 request.load_flags = 0;
6676
6677 MockRead data_reads[] = {
6678 MockRead("HTTP/1.1 200 OK\r\n"),
6679 MockRead(kAlternateProtocolHttpHeader),
6680 MockRead("hello world"),
6681 MockRead(true, OK),
6682 };
6683
6684 StaticSocketDataProvider first_transaction(
6685 data_reads, arraysize(data_reads), NULL, 0);
6686 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6687 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6688
6689 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6690 StaticSocketDataProvider hanging_socket(
6691 NULL, 0, NULL, 0);
6692 hanging_socket.set_connect_data(never_finishing_connect);
6693 // Socket 2 and 3 are the hanging Alternate-Protocol and
6694 // non-Alternate-Protocol jobs from the 2nd transaction.
6695 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6696 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6697
6698 SSLSocketDataProvider ssl(true, OK);
6699 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6700 ssl.next_proto = "spdy/2";
6701 ssl.was_npn_negotiated = true;
6702 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6703
6704 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6705 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6706 MockWrite spdy_writes[] = {
6707 CreateMockWrite(*req1),
6708 CreateMockWrite(*req2),
6709 };
6710 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6711 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6712 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6713 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6714 MockRead spdy_reads[] = {
6715 CreateMockRead(*resp1),
6716 CreateMockRead(*data1),
6717 CreateMockRead(*resp2),
6718 CreateMockRead(*data2),
6719 MockRead(true, 0, 0),
6720 };
6721
6722 scoped_refptr<DelayedSocketData> spdy_data(
6723 new DelayedSocketData(
6724 2, // wait for writes to finish before reading.
6725 spdy_reads, arraysize(spdy_reads),
6726 spdy_writes, arraysize(spdy_writes)));
6727 // Socket 4 is the successful Alternate-Protocol for transaction 3.
6728 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6729
6730 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6731 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6732
6733 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6734 TestCompletionCallback callback1;
6735 HttpNetworkTransaction trans1(session);
6736
6737 int rv = trans1.Start(&request, &callback1, BoundNetLog());
6738 EXPECT_EQ(ERR_IO_PENDING, rv);
6739 EXPECT_EQ(OK, callback1.WaitForResult());
6740
6741 const HttpResponseInfo* response = trans1.GetResponseInfo();
6742 ASSERT_TRUE(response != NULL);
6743 ASSERT_TRUE(response->headers != NULL);
6744 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6745
6746 std::string response_data;
6747 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6748 EXPECT_EQ("hello world", response_data);
6749
6750 TestCompletionCallback callback2;
6751 HttpNetworkTransaction trans2(session);
6752 rv = trans2.Start(&request, &callback2, BoundNetLog());
6753 EXPECT_EQ(ERR_IO_PENDING, rv);
6754
6755 TestCompletionCallback callback3;
6756 HttpNetworkTransaction trans3(session);
6757 rv = trans3.Start(&request, &callback3, BoundNetLog());
6758 EXPECT_EQ(ERR_IO_PENDING, rv);
6759
6760 EXPECT_EQ(OK, callback2.WaitForResult());
6761 EXPECT_EQ(OK, callback3.WaitForResult());
6762
6763 response = trans2.GetResponseInfo();
6764 ASSERT_TRUE(response != NULL);
6765 ASSERT_TRUE(response->headers != NULL);
6766 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6767 EXPECT_TRUE(response->was_fetched_via_spdy);
6768 EXPECT_TRUE(response->was_npn_negotiated);
6769 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6770 EXPECT_EQ("hello!", response_data);
6771
6772 response = trans3.GetResponseInfo();
6773 ASSERT_TRUE(response != NULL);
6774 ASSERT_TRUE(response->headers != NULL);
6775 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6776 EXPECT_TRUE(response->was_fetched_via_spdy);
6777 EXPECT_TRUE(response->was_npn_negotiated);
6778 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6779 EXPECT_EQ("hello!", response_data);
6780
6781 HttpStreamFactory::set_next_protos("");
6782 HttpStreamFactory::set_use_alternate_protocols(false);
6783}
6784
6785TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6786 HttpStreamFactory::set_use_alternate_protocols(true);
6787 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6788 SessionDependencies session_deps;
6789
6790 HttpRequestInfo request;
6791 request.method = "GET";
6792 request.url = GURL("http://www.google.com/");
6793 request.load_flags = 0;
6794
6795 MockRead data_reads[] = {
6796 MockRead("HTTP/1.1 200 OK\r\n"),
6797 MockRead(kAlternateProtocolHttpHeader),
6798 MockRead("hello world"),
6799 MockRead(true, OK),
6800 };
6801
6802 StaticSocketDataProvider first_transaction(
6803 data_reads, arraysize(data_reads), NULL, 0);
6804 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6805
6806 SSLSocketDataProvider ssl(true, OK);
6807 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6808 ssl.next_proto = "spdy/2";
6809 ssl.was_npn_negotiated = true;
6810 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6811
6812 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6813 StaticSocketDataProvider hanging_alternate_protocol_socket(
6814 NULL, 0, NULL, 0);
6815 hanging_alternate_protocol_socket.set_connect_data(
6816 never_finishing_connect);
6817 session_deps.socket_factory.AddSocketDataProvider(
6818 &hanging_alternate_protocol_socket);
6819
6820 // 2nd request is just a copy of the first one, over HTTP again.
6821 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6822
6823 TestCompletionCallback callback;
6824
6825 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6826 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6827
6828 int rv = trans->Start(&request, &callback, BoundNetLog());
6829 EXPECT_EQ(ERR_IO_PENDING, rv);
6830 EXPECT_EQ(OK, callback.WaitForResult());
6831
6832 const HttpResponseInfo* response = trans->GetResponseInfo();
6833 ASSERT_TRUE(response != NULL);
6834 ASSERT_TRUE(response->headers != NULL);
6835 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6836
6837 std::string response_data;
6838 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6839 EXPECT_EQ("hello world", response_data);
6840
6841 trans.reset(new HttpNetworkTransaction(session));
6842
6843 rv = trans->Start(&request, &callback, BoundNetLog());
6844 EXPECT_EQ(ERR_IO_PENDING, rv);
6845 EXPECT_EQ(OK, callback.WaitForResult());
6846
6847 response = trans->GetResponseInfo();
6848 ASSERT_TRUE(response != NULL);
6849 ASSERT_TRUE(response->headers != NULL);
6850 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6851 EXPECT_FALSE(response->was_fetched_via_spdy);
6852 EXPECT_FALSE(response->was_npn_negotiated);
6853
6854 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6855 EXPECT_EQ("hello world", response_data);
6856
6857 HttpStreamFactory::set_next_protos("");
6858 HttpStreamFactory::set_use_alternate_protocols(false);
6859}
6860
[email protected]631f1322010-04-30 17:59:116861class CapturingProxyResolver : public ProxyResolver {
6862 public:
6863 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6864 virtual ~CapturingProxyResolver() {}
6865
6866 virtual int GetProxyForURL(const GURL& url,
6867 ProxyInfo* results,
6868 CompletionCallback* callback,
6869 RequestHandle* request,
6870 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406871 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6872 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426873 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116874 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426875 return OK;
[email protected]631f1322010-04-30 17:59:116876 }
6877
6878 virtual void CancelRequest(RequestHandle request) {
6879 NOTREACHED();
6880 }
6881
[email protected]1e605472010-12-16 21:41:406882 virtual void CancelSetPacScript() {
6883 NOTREACHED();
6884 }
6885
[email protected]24476402010-07-20 20:55:176886 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116887 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426888 return OK;
[email protected]631f1322010-04-30 17:59:116889 }
6890
[email protected]24476402010-07-20 20:55:176891 const std::vector<GURL>& resolved() const { return resolved_; }
6892
6893 private:
[email protected]631f1322010-04-30 17:59:116894 std::vector<GURL> resolved_;
6895
6896 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6897};
6898
[email protected]631f1322010-04-30 17:59:116899TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386900 HttpStreamFactory::set_use_alternate_protocols(true);
6901 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116902
6903 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426904 proxy_config.set_auto_detect(true);
6905 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116906
[email protected]631f1322010-04-30 17:59:116907 CapturingProxyResolver* capturing_proxy_resolver =
6908 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386909 SessionDependencies session_deps(new ProxyService(
6910 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6911 NULL));
[email protected]631f1322010-04-30 17:59:116912
6913 HttpRequestInfo request;
6914 request.method = "GET";
6915 request.url = GURL("http://www.google.com/");
6916 request.load_flags = 0;
6917
6918 MockRead data_reads[] = {
6919 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356920 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116921 MockRead("hello world"),
6922 MockRead(true, OK),
6923 };
6924
6925 StaticSocketDataProvider first_transaction(
6926 data_reads, arraysize(data_reads), NULL, 0);
6927 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6928
6929 SSLSocketDataProvider ssl(true, OK);
6930 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356931 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536932 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116933 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6934
[email protected]2bd93022010-07-17 00:58:446935 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116936 MockWrite spdy_writes[] = {
6937 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6938 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426939 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136940 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116941 };
6942
[email protected]d911f1b2010-05-05 22:39:426943 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6944
[email protected]2bd93022010-07-17 00:58:446945 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6946 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116947 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426948 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136949 CreateMockRead(*resp.get(), 4), // 2, 4
6950 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426951 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116952 };
6953
[email protected]d911f1b2010-05-05 22:39:426954 scoped_refptr<OrderedSocketData> spdy_data(
6955 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116956 spdy_reads, arraysize(spdy_reads),
6957 spdy_writes, arraysize(spdy_writes)));
6958 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6959
[email protected]2d6728692011-03-12 01:39:556960 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6961 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6962 NULL, 0, NULL, 0);
6963 hanging_non_alternate_protocol_socket.set_connect_data(
6964 never_finishing_connect);
6965 session_deps.socket_factory.AddSocketDataProvider(
6966 &hanging_non_alternate_protocol_socket);
6967
[email protected]631f1322010-04-30 17:59:116968 TestCompletionCallback callback;
6969
6970 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6971 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6972
6973 int rv = trans->Start(&request, &callback, BoundNetLog());
6974 EXPECT_EQ(ERR_IO_PENDING, rv);
6975 EXPECT_EQ(OK, callback.WaitForResult());
6976
6977 const HttpResponseInfo* response = trans->GetResponseInfo();
6978 ASSERT_TRUE(response != NULL);
6979 ASSERT_TRUE(response->headers != NULL);
6980 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536981 EXPECT_FALSE(response->was_fetched_via_spdy);
6982 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116983
6984 std::string response_data;
6985 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6986 EXPECT_EQ("hello world", response_data);
6987
6988 trans.reset(new HttpNetworkTransaction(session));
6989
6990 rv = trans->Start(&request, &callback, BoundNetLog());
6991 EXPECT_EQ(ERR_IO_PENDING, rv);
6992 EXPECT_EQ(OK, callback.WaitForResult());
6993
6994 response = trans->GetResponseInfo();
6995 ASSERT_TRUE(response != NULL);
6996 ASSERT_TRUE(response->headers != NULL);
6997 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536998 EXPECT_TRUE(response->was_fetched_via_spdy);
6999 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117000
7001 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7002 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557003 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427004 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117005 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427006 EXPECT_EQ("https://www.google.com/",
7007 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117008
[email protected]8e6441ca2010-08-19 05:56:387009 HttpStreamFactory::set_next_protos("");
7010 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117011}
[email protected]631f1322010-04-30 17:59:117012
[email protected]2ff8b312010-04-26 22:20:547013TEST_F(HttpNetworkTransactionTest,
7014 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387015 HttpStreamFactory::set_use_alternate_protocols(true);
7016 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:547017 SessionDependencies session_deps;
7018
7019 HttpRequestInfo request;
7020 request.method = "GET";
7021 request.url = GURL("http://www.google.com/");
7022 request.load_flags = 0;
7023
7024 MockRead data_reads[] = {
7025 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357026 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547027 MockRead("hello world"),
7028 MockRead(true, OK),
7029 };
7030
7031 StaticSocketDataProvider first_transaction(
7032 data_reads, arraysize(data_reads), NULL, 0);
7033 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7034
7035 SSLSocketDataProvider ssl(true, OK);
7036 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357037 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537038 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:547039 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537040 // Make sure we use ssl for spdy here.
7041 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547042
[email protected]2bd93022010-07-17 00:58:447043 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137044 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547045
[email protected]2bd93022010-07-17 00:58:447046 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7047 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547048 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137049 CreateMockRead(*resp),
7050 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547051 MockRead(true, 0, 0),
7052 };
7053
7054 scoped_refptr<DelayedSocketData> spdy_data(
7055 new DelayedSocketData(
7056 1, // wait for one write to finish before reading.
7057 spdy_reads, arraysize(spdy_reads),
7058 spdy_writes, arraysize(spdy_writes)));
7059 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7060
7061 TestCompletionCallback callback;
7062
7063 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7064
7065 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7066
[email protected]5a1d7ca2010-04-28 20:12:277067 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547068 EXPECT_EQ(ERR_IO_PENDING, rv);
7069 EXPECT_EQ(OK, callback.WaitForResult());
7070
7071 const HttpResponseInfo* response = trans->GetResponseInfo();
7072 ASSERT_TRUE(response != NULL);
7073 ASSERT_TRUE(response->headers != NULL);
7074 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7075
7076 std::string response_data;
7077 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7078 EXPECT_EQ("hello world", response_data);
7079
7080 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387081 HostPortPair host_port_pair("www.google.com", 443);
7082 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547083 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317084 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287085 scoped_refptr<TransportSocketParams> transport_params(
7086 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:387087
7088 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7089 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287090 connection->Init(host_port_pair.ToString(),
7091 transport_params,
7092 LOWEST,
7093 &callback,
7094 session->transport_socket_pool(),
[email protected]02b0c342010-09-25 21:09:387095 BoundNetLog()));
7096 EXPECT_EQ(OK, callback.WaitForResult());
7097
7098 SSLConfig ssl_config;
7099 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347100 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177101 SSLClientSocketContext context;
7102 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347103 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7104 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177105 NULL /* ssl_host_info */, context));
[email protected]9e1bdd32011-02-03 21:48:347106 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:387107 EXPECT_EQ(OK, callback.WaitForResult());
7108
[email protected]9e1bdd32011-02-03 21:48:347109 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387110 true, OK));
7111
[email protected]2ff8b312010-04-26 22:20:547112 trans.reset(new HttpNetworkTransaction(session));
7113
[email protected]5a1d7ca2010-04-28 20:12:277114 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547115 EXPECT_EQ(ERR_IO_PENDING, rv);
7116 EXPECT_EQ(OK, callback.WaitForResult());
7117
7118 response = trans->GetResponseInfo();
7119 ASSERT_TRUE(response != NULL);
7120 ASSERT_TRUE(response->headers != NULL);
7121 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537122 EXPECT_TRUE(response->was_fetched_via_spdy);
7123 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547124
7125 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7126 EXPECT_EQ("hello!", response_data);
7127
[email protected]8e6441ca2010-08-19 05:56:387128 HttpStreamFactory::set_next_protos("");
7129 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427130}
7131
[email protected]044de0642010-06-17 10:42:157132// GenerateAuthToken is a mighty big test.
7133// It tests all permutation of GenerateAuthToken behavior:
7134// - Synchronous and Asynchronous completion.
7135// - OK or error on completion.
7136// - Direct connection, non-authenticating proxy, and authenticating proxy.
7137// - HTTP or HTTPS backend (to include proxy tunneling).
7138// - Non-authenticating and authenticating backend.
7139//
7140// In all, there are 44 reasonable permuations (for example, if there are
7141// problems generating an auth token for an authenticating proxy, we don't
7142// need to test all permutations of the backend server).
7143//
7144// The test proceeds by going over each of the configuration cases, and
7145// potentially running up to three rounds in each of the tests. The TestConfig
7146// specifies both the configuration for the test as well as the expectations
7147// for the results.
7148TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507149 static const char kServer[] = "http://www.example.com";
7150 static const char kSecureServer[] = "https://www.example.com";
7151 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157152 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7153
7154 enum AuthTiming {
7155 AUTH_NONE,
7156 AUTH_SYNC,
7157 AUTH_ASYNC,
7158 };
7159
7160 const MockWrite kGet(
7161 "GET / HTTP/1.1\r\n"
7162 "Host: www.example.com\r\n"
7163 "Connection: keep-alive\r\n\r\n");
7164 const MockWrite kGetProxy(
7165 "GET http://www.example.com/ HTTP/1.1\r\n"
7166 "Host: www.example.com\r\n"
7167 "Proxy-Connection: keep-alive\r\n\r\n");
7168 const MockWrite kGetAuth(
7169 "GET / HTTP/1.1\r\n"
7170 "Host: www.example.com\r\n"
7171 "Connection: keep-alive\r\n"
7172 "Authorization: auth_token\r\n\r\n");
7173 const MockWrite kGetProxyAuth(
7174 "GET http://www.example.com/ HTTP/1.1\r\n"
7175 "Host: www.example.com\r\n"
7176 "Proxy-Connection: keep-alive\r\n"
7177 "Proxy-Authorization: auth_token\r\n\r\n");
7178 const MockWrite kGetAuthThroughProxy(
7179 "GET http://www.example.com/ HTTP/1.1\r\n"
7180 "Host: www.example.com\r\n"
7181 "Proxy-Connection: keep-alive\r\n"
7182 "Authorization: auth_token\r\n\r\n");
7183 const MockWrite kGetAuthWithProxyAuth(
7184 "GET http://www.example.com/ HTTP/1.1\r\n"
7185 "Host: www.example.com\r\n"
7186 "Proxy-Connection: keep-alive\r\n"
7187 "Proxy-Authorization: auth_token\r\n"
7188 "Authorization: auth_token\r\n\r\n");
7189 const MockWrite kConnect(
7190 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7191 "Host: www.example.com\r\n"
7192 "Proxy-Connection: keep-alive\r\n\r\n");
7193 const MockWrite kConnectProxyAuth(
7194 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7195 "Host: www.example.com\r\n"
7196 "Proxy-Connection: keep-alive\r\n"
7197 "Proxy-Authorization: auth_token\r\n\r\n");
7198
7199 const MockRead kSuccess(
7200 "HTTP/1.1 200 OK\r\n"
7201 "Content-Type: text/html; charset=iso-8859-1\r\n"
7202 "Content-Length: 3\r\n\r\n"
7203 "Yes");
7204 const MockRead kFailure(
7205 "Should not be called.");
7206 const MockRead kServerChallenge(
7207 "HTTP/1.1 401 Unauthorized\r\n"
7208 "WWW-Authenticate: Mock realm=server\r\n"
7209 "Content-Type: text/html; charset=iso-8859-1\r\n"
7210 "Content-Length: 14\r\n\r\n"
7211 "Unauthorized\r\n");
7212 const MockRead kProxyChallenge(
7213 "HTTP/1.1 407 Unauthorized\r\n"
7214 "Proxy-Authenticate: Mock realm=proxy\r\n"
7215 "Proxy-Connection: close\r\n"
7216 "Content-Type: text/html; charset=iso-8859-1\r\n"
7217 "Content-Length: 14\r\n\r\n"
7218 "Unauthorized\r\n");
7219 const MockRead kProxyConnected(
7220 "HTTP/1.1 200 Connection Established\r\n\r\n");
7221
7222 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7223 // no constructors, but the C++ compiler on Windows warns about
7224 // unspecified data in compound literals. So, moved to using constructors,
7225 // and TestRound's created with the default constructor should not be used.
7226 struct TestRound {
7227 TestRound()
7228 : expected_rv(ERR_UNEXPECTED),
7229 extra_write(NULL),
7230 extra_read(NULL) {
7231 }
7232 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7233 int expected_rv_arg)
7234 : write(write_arg),
7235 read(read_arg),
7236 expected_rv(expected_rv_arg),
7237 extra_write(NULL),
7238 extra_read(NULL) {
7239 }
7240 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7241 int expected_rv_arg, const MockWrite* extra_write_arg,
7242 const MockWrite* extra_read_arg)
7243 : write(write_arg),
7244 read(read_arg),
7245 expected_rv(expected_rv_arg),
7246 extra_write(extra_write_arg),
7247 extra_read(extra_read_arg) {
7248 }
7249 MockWrite write;
7250 MockRead read;
7251 int expected_rv;
7252 const MockWrite* extra_write;
7253 const MockRead* extra_read;
7254 };
7255
7256 static const int kNoSSL = 500;
7257
7258 struct TestConfig {
7259 const char* proxy_url;
7260 AuthTiming proxy_auth_timing;
7261 int proxy_auth_rv;
7262 const char* server_url;
7263 AuthTiming server_auth_timing;
7264 int server_auth_rv;
7265 int num_auth_rounds;
7266 int first_ssl_round;
7267 TestRound rounds[3];
7268 } test_configs[] = {
7269 // Non-authenticating HTTP server with a direct connection.
7270 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7271 { TestRound(kGet, kSuccess, OK)}},
7272 // Authenticating HTTP server with a direct connection.
7273 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7274 { TestRound(kGet, kServerChallenge, OK),
7275 TestRound(kGetAuth, kSuccess, OK)}},
7276 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7277 { TestRound(kGet, kServerChallenge, OK),
7278 TestRound(kGetAuth, kFailure, kAuthErr)}},
7279 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7280 { TestRound(kGet, kServerChallenge, OK),
7281 TestRound(kGetAuth, kSuccess, OK)}},
7282 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7283 { TestRound(kGet, kServerChallenge, OK),
7284 TestRound(kGetAuth, kFailure, kAuthErr)}},
7285 // Non-authenticating HTTP server through a non-authenticating proxy.
7286 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7287 { TestRound(kGetProxy, kSuccess, OK)}},
7288 // Authenticating HTTP server through a non-authenticating proxy.
7289 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7290 { TestRound(kGetProxy, kServerChallenge, OK),
7291 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7292 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7293 { TestRound(kGetProxy, kServerChallenge, OK),
7294 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7295 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7296 { TestRound(kGetProxy, kServerChallenge, OK),
7297 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7298 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7299 { TestRound(kGetProxy, kServerChallenge, OK),
7300 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7301 // Non-authenticating HTTP server through an authenticating proxy.
7302 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7303 { TestRound(kGetProxy, kProxyChallenge, OK),
7304 TestRound(kGetProxyAuth, kSuccess, OK)}},
7305 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7306 { TestRound(kGetProxy, kProxyChallenge, OK),
7307 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7308 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7309 { TestRound(kGetProxy, kProxyChallenge, OK),
7310 TestRound(kGetProxyAuth, kSuccess, OK)}},
7311 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7312 { TestRound(kGetProxy, kProxyChallenge, OK),
7313 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7314 // Authenticating HTTP server through an authenticating proxy.
7315 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7316 { TestRound(kGetProxy, kProxyChallenge, OK),
7317 TestRound(kGetProxyAuth, kServerChallenge, OK),
7318 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7319 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7320 { TestRound(kGetProxy, kProxyChallenge, OK),
7321 TestRound(kGetProxyAuth, kServerChallenge, OK),
7322 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7323 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7324 { TestRound(kGetProxy, kProxyChallenge, OK),
7325 TestRound(kGetProxyAuth, kServerChallenge, OK),
7326 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7327 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7328 { TestRound(kGetProxy, kProxyChallenge, OK),
7329 TestRound(kGetProxyAuth, kServerChallenge, OK),
7330 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7331 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7332 { TestRound(kGetProxy, kProxyChallenge, OK),
7333 TestRound(kGetProxyAuth, kServerChallenge, OK),
7334 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7335 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7336 { TestRound(kGetProxy, kProxyChallenge, OK),
7337 TestRound(kGetProxyAuth, kServerChallenge, OK),
7338 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7339 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7340 { TestRound(kGetProxy, kProxyChallenge, OK),
7341 TestRound(kGetProxyAuth, kServerChallenge, OK),
7342 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7343 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7344 { TestRound(kGetProxy, kProxyChallenge, OK),
7345 TestRound(kGetProxyAuth, kServerChallenge, OK),
7346 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7347 // Non-authenticating HTTPS server with a direct connection.
7348 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7349 { TestRound(kGet, kSuccess, OK)}},
7350 // Authenticating HTTPS server with a direct connection.
7351 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7352 { TestRound(kGet, kServerChallenge, OK),
7353 TestRound(kGetAuth, kSuccess, OK)}},
7354 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7355 { TestRound(kGet, kServerChallenge, OK),
7356 TestRound(kGetAuth, kFailure, kAuthErr)}},
7357 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7358 { TestRound(kGet, kServerChallenge, OK),
7359 TestRound(kGetAuth, kSuccess, OK)}},
7360 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7361 { TestRound(kGet, kServerChallenge, OK),
7362 TestRound(kGetAuth, kFailure, kAuthErr)}},
7363 // Non-authenticating HTTPS server with a non-authenticating proxy.
7364 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7365 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7366 // Authenticating HTTPS server through a non-authenticating proxy.
7367 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7368 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7369 TestRound(kGetAuth, kSuccess, OK)}},
7370 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7371 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7372 TestRound(kGetAuth, kFailure, kAuthErr)}},
7373 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7374 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7375 TestRound(kGetAuth, kSuccess, OK)}},
7376 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7377 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7378 TestRound(kGetAuth, kFailure, kAuthErr)}},
7379 // Non-Authenticating HTTPS server through an authenticating proxy.
7380 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7381 { TestRound(kConnect, kProxyChallenge, OK),
7382 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7383 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7384 { TestRound(kConnect, kProxyChallenge, OK),
7385 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7386 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7387 { TestRound(kConnect, kProxyChallenge, OK),
7388 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7389 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7390 { TestRound(kConnect, kProxyChallenge, OK),
7391 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7392 // Authenticating HTTPS server through an authenticating proxy.
7393 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7394 { TestRound(kConnect, kProxyChallenge, OK),
7395 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7396 &kGet, &kServerChallenge),
7397 TestRound(kGetAuth, kSuccess, OK)}},
7398 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7399 { TestRound(kConnect, kProxyChallenge, OK),
7400 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7401 &kGet, &kServerChallenge),
7402 TestRound(kGetAuth, kFailure, kAuthErr)}},
7403 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7404 { TestRound(kConnect, kProxyChallenge, OK),
7405 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7406 &kGet, &kServerChallenge),
7407 TestRound(kGetAuth, kSuccess, OK)}},
7408 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7409 { TestRound(kConnect, kProxyChallenge, OK),
7410 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7411 &kGet, &kServerChallenge),
7412 TestRound(kGetAuth, kFailure, kAuthErr)}},
7413 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7414 { TestRound(kConnect, kProxyChallenge, OK),
7415 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7416 &kGet, &kServerChallenge),
7417 TestRound(kGetAuth, kSuccess, OK)}},
7418 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7419 { TestRound(kConnect, kProxyChallenge, OK),
7420 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7421 &kGet, &kServerChallenge),
7422 TestRound(kGetAuth, kFailure, kAuthErr)}},
7423 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7424 { TestRound(kConnect, kProxyChallenge, OK),
7425 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7426 &kGet, &kServerChallenge),
7427 TestRound(kGetAuth, kSuccess, OK)}},
7428 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7429 { TestRound(kConnect, kProxyChallenge, OK),
7430 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7431 &kGet, &kServerChallenge),
7432 TestRound(kGetAuth, kFailure, kAuthErr)}},
7433 };
7434
7435 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007436 HttpAuthHandlerMock::Factory* auth_factory(
7437 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157438 session_deps.http_auth_handler_factory.reset(auth_factory);
7439
7440 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7441 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267442
7443 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157444 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007445 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157446 std::string auth_challenge = "Mock realm=proxy";
7447 GURL origin(test_config.proxy_url);
7448 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7449 auth_challenge.end());
7450 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7451 origin, BoundNetLog());
7452 auth_handler->SetGenerateExpectation(
7453 test_config.proxy_auth_timing == AUTH_ASYNC,
7454 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157455 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7456 }
7457 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007458 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157459 std::string auth_challenge = "Mock realm=server";
7460 GURL origin(test_config.server_url);
7461 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7462 auth_challenge.end());
7463 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7464 origin, BoundNetLog());
7465 auth_handler->SetGenerateExpectation(
7466 test_config.server_auth_timing == AUTH_ASYNC,
7467 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157468 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7469 }
7470 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127471 session_deps.proxy_service.reset(
7472 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157473 } else {
[email protected]6104ea5d2011-04-27 21:37:127474 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157475 }
7476
7477 HttpRequestInfo request;
7478 request.method = "GET";
7479 request.url = GURL(test_config.server_url);
7480 request.load_flags = 0;
7481
[email protected]0b0bf032010-09-21 18:08:507482 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7483 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157484
7485 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7486 const TestRound& read_write_round = test_config.rounds[round];
7487
7488 // Set up expected reads and writes.
7489 MockRead reads[2];
7490 reads[0] = read_write_round.read;
7491 size_t length_reads = 1;
7492 if (read_write_round.extra_read) {
7493 reads[1] = *read_write_round.extra_read;
7494 length_reads = 2;
7495 }
7496
7497 MockWrite writes[2];
7498 writes[0] = read_write_round.write;
7499 size_t length_writes = 1;
7500 if (read_write_round.extra_write) {
7501 writes[1] = *read_write_round.extra_write;
7502 length_writes = 2;
7503 }
7504 StaticSocketDataProvider data_provider(
7505 reads, length_reads, writes, length_writes);
7506 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7507
7508 // Add an SSL sequence if necessary.
7509 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7510 if (round >= test_config.first_ssl_round)
7511 session_deps.socket_factory.AddSSLSocketDataProvider(
7512 &ssl_socket_data_provider);
7513
7514 // Start or restart the transaction.
7515 TestCompletionCallback callback;
7516 int rv;
7517 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507518 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157519 } else {
[email protected]0b0bf032010-09-21 18:08:507520 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157521 }
7522 if (rv == ERR_IO_PENDING)
7523 rv = callback.WaitForResult();
7524
7525 // Compare results with expected data.
7526 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507527 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157528 if (read_write_round.expected_rv == OK) {
7529 EXPECT_FALSE(response == NULL);
7530 } else {
7531 EXPECT_TRUE(response == NULL);
7532 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7533 continue;
7534 }
7535 if (round + 1 < test_config.num_auth_rounds) {
7536 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7537 } else {
7538 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7539 }
7540 }
[email protected]e5ae96a2010-04-14 20:12:457541 }
7542}
7543
[email protected]c871bce92010-07-15 21:51:147544TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7545 // Do multi-round authentication and make sure it works correctly.
7546 SessionDependencies session_deps;
7547 HttpAuthHandlerMock::Factory* auth_factory(
7548 new HttpAuthHandlerMock::Factory());
7549 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127550 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147551 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7552 session_deps.host_resolver->set_synchronous_mode(true);
7553
7554 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7555 auth_handler->set_connection_based(true);
7556 std::string auth_challenge = "Mock realm=server";
7557 GURL origin("http://www.example.com");
7558 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7559 auth_challenge.end());
7560 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7561 origin, BoundNetLog());
7562 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7563
[email protected]c871bce92010-07-15 21:51:147564 int rv = OK;
7565 const HttpResponseInfo* response = NULL;
7566 HttpRequestInfo request;
7567 request.method = "GET";
7568 request.url = origin;
7569 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277570
7571 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107572
7573 // Use a TCP Socket Pool with only one connection per group. This is used
7574 // to validate that the TCP socket is not released to the pool between
7575 // each round of multi-round authentication.
7576 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287577 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7578 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107579 50, // Max sockets for pool
7580 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287581 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107582 session_deps.host_resolver.get(),
7583 &session_deps.socket_factory,
7584 session_deps.net_log);
[email protected]ab739042011-04-07 15:22:287585 session_peer.SetTransportSocketPool(transport_pool);
[email protected]7ef4cbbb2011-02-06 11:19:107586
[email protected]cb9bf6ca2011-01-28 13:15:277587 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c871bce92010-07-15 21:51:147588 TestCompletionCallback callback;
7589
7590 const MockWrite kGet(
7591 "GET / HTTP/1.1\r\n"
7592 "Host: www.example.com\r\n"
7593 "Connection: keep-alive\r\n\r\n");
7594 const MockWrite kGetAuth(
7595 "GET / HTTP/1.1\r\n"
7596 "Host: www.example.com\r\n"
7597 "Connection: keep-alive\r\n"
7598 "Authorization: auth_token\r\n\r\n");
7599
7600 const MockRead kServerChallenge(
7601 "HTTP/1.1 401 Unauthorized\r\n"
7602 "WWW-Authenticate: Mock realm=server\r\n"
7603 "Content-Type: text/html; charset=iso-8859-1\r\n"
7604 "Content-Length: 14\r\n\r\n"
7605 "Unauthorized\r\n");
7606 const MockRead kSuccess(
7607 "HTTP/1.1 200 OK\r\n"
7608 "Content-Type: text/html; charset=iso-8859-1\r\n"
7609 "Content-Length: 3\r\n\r\n"
7610 "Yes");
7611
7612 MockWrite writes[] = {
7613 // First round
7614 kGet,
7615 // Second round
7616 kGetAuth,
7617 // Third round
7618 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307619 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107620 kGetAuth,
7621 // Competing request
7622 kGet,
[email protected]c871bce92010-07-15 21:51:147623 };
7624 MockRead reads[] = {
7625 // First round
7626 kServerChallenge,
7627 // Second round
7628 kServerChallenge,
7629 // Third round
[email protected]eca50e122010-09-11 14:03:307630 kServerChallenge,
7631 // Fourth round
[email protected]c871bce92010-07-15 21:51:147632 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107633 // Competing response
7634 kSuccess,
[email protected]c871bce92010-07-15 21:51:147635 };
7636 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7637 writes, arraysize(writes));
7638 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7639
[email protected]7ef4cbbb2011-02-06 11:19:107640 const char* const kSocketGroup = "www.example.com:80";
7641
7642 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147643 auth_handler->SetGenerateExpectation(false, OK);
7644 rv = trans->Start(&request, &callback, BoundNetLog());
7645 if (rv == ERR_IO_PENDING)
7646 rv = callback.WaitForResult();
7647 EXPECT_EQ(OK, rv);
7648 response = trans->GetResponseInfo();
7649 ASSERT_FALSE(response == NULL);
7650 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287651 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147652
[email protected]7ef4cbbb2011-02-06 11:19:107653 // In between rounds, another request comes in for the same domain.
7654 // It should not be able to grab the TCP socket that trans has already
7655 // claimed.
7656 scoped_ptr<HttpTransaction> trans_compete(
7657 new HttpNetworkTransaction(session));
7658 TestCompletionCallback callback_compete;
7659 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7660 EXPECT_EQ(ERR_IO_PENDING, rv);
7661 // callback_compete.WaitForResult at this point would stall forever,
7662 // since the HttpNetworkTransaction does not release the request back to
7663 // the pool until after authentication completes.
7664
7665 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147666 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447667 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147668 if (rv == ERR_IO_PENDING)
7669 rv = callback.WaitForResult();
7670 EXPECT_EQ(OK, rv);
7671 response = trans->GetResponseInfo();
7672 ASSERT_FALSE(response == NULL);
7673 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287674 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147675
[email protected]7ef4cbbb2011-02-06 11:19:107676 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147677 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447678 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147679 if (rv == ERR_IO_PENDING)
7680 rv = callback.WaitForResult();
7681 EXPECT_EQ(OK, rv);
7682 response = trans->GetResponseInfo();
7683 ASSERT_FALSE(response == NULL);
7684 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287685 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307686
[email protected]7ef4cbbb2011-02-06 11:19:107687 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307688 auth_handler->SetGenerateExpectation(false, OK);
7689 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7690 if (rv == ERR_IO_PENDING)
7691 rv = callback.WaitForResult();
7692 EXPECT_EQ(OK, rv);
7693 response = trans->GetResponseInfo();
7694 ASSERT_FALSE(response == NULL);
7695 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287696 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107697
7698 // Read the body since the fourth round was successful. This will also
7699 // release the socket back to the pool.
7700 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7701 rv = trans->Read(io_buf, io_buf->size(), &callback);
7702 if (rv == ERR_IO_PENDING)
7703 rv = callback.WaitForResult();
7704 EXPECT_EQ(3, rv);
7705 rv = trans->Read(io_buf, io_buf->size(), &callback);
7706 EXPECT_EQ(0, rv);
7707 // There are still 0 idle sockets, since the trans_compete transaction
7708 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287709 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107710
7711 // The competing request can now finish. Wait for the headers and then
7712 // read the body.
7713 rv = callback_compete.WaitForResult();
7714 EXPECT_EQ(OK, rv);
7715 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7716 if (rv == ERR_IO_PENDING)
7717 rv = callback.WaitForResult();
7718 EXPECT_EQ(3, rv);
7719 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7720 EXPECT_EQ(0, rv);
7721
7722 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287723 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147724}
7725
[email protected]aeaca1f2010-04-20 22:05:217726class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7727 public:
[email protected]06650c52010-06-03 00:49:177728 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217729 : fail_all_(fail_all) {
7730 }
7731
7732 virtual MockRead GetNextRead() {
7733 if (fail_all_)
7734 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7735
7736 return MockRead(false /* async */,
7737 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7738 }
7739
7740 virtual MockWriteResult OnWrite(const std::string& data) {
7741 return MockWriteResult(false /* async */, data.size());
7742 }
7743
7744 void Reset() {
7745 }
7746
7747 private:
7748 const bool fail_all_;
7749};
7750
7751// Test that we restart a connection when we see a decompression failure from
7752// the peer during the handshake. (In the real world we'll restart with SSLv3
7753// and we won't offer DEFLATE in that case.)
7754TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7755 HttpRequestInfo request;
7756 request.method = "GET";
7757 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7758 request.load_flags = 0;
7759
7760 SessionDependencies session_deps;
7761 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7762 false /* fail all reads */);
7763 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7764 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117765 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217766 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7767 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7768 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7769 session_deps.socket_factory.AddSSLSocketDataProvider(
7770 &ssl_socket_data_provider1);
7771 session_deps.socket_factory.AddSSLSocketDataProvider(
7772 &ssl_socket_data_provider2);
7773
[email protected]e60e47a2010-07-14 03:37:187774 // Work around http://crbug.com/37454
7775 StaticSocketDataProvider bug37454_connection;
7776 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7777 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7778
[email protected]aeaca1f2010-04-20 22:05:217779 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7780 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7781 TestCompletionCallback callback;
7782
[email protected]5a1d7ca2010-04-28 20:12:277783 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217784 EXPECT_EQ(ERR_IO_PENDING, rv);
7785 EXPECT_EQ(OK, callback.WaitForResult());
7786
7787 const HttpResponseInfo* response = trans->GetResponseInfo();
7788 ASSERT_TRUE(response != NULL);
7789 ASSERT_TRUE(response->headers != NULL);
7790 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7791
7792 std::string response_data;
7793 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7794 EXPECT_EQ("ok.", response_data);
7795}
7796
7797// Test that we restart a connection if we get a decompression failure from the
7798// peer while reading the first bytes from the connection. This occurs when the
7799// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7800// in the handshake.
7801TEST_F(HttpNetworkTransactionTest,
7802 RestartAfterTLSDecompressionFailureWithFalseStart) {
7803 HttpRequestInfo request;
7804 request.method = "GET";
7805 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7806 request.load_flags = 0;
7807
7808 SessionDependencies session_deps;
7809 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7810 true /* fail all reads */);
7811 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7812 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7813 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7814 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7815 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7816 session_deps.socket_factory.AddSSLSocketDataProvider(
7817 &ssl_socket_data_provider1);
7818 session_deps.socket_factory.AddSSLSocketDataProvider(
7819 &ssl_socket_data_provider2);
7820
7821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7822 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7823 TestCompletionCallback callback;
7824
[email protected]5a1d7ca2010-04-28 20:12:277825 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217826 EXPECT_EQ(ERR_IO_PENDING, rv);
7827 EXPECT_EQ(OK, callback.WaitForResult());
7828
7829 const HttpResponseInfo* response = trans->GetResponseInfo();
7830 ASSERT_TRUE(response != NULL);
7831 ASSERT_TRUE(response->headers != NULL);
7832 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7833
7834 std::string response_data;
7835 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7836 EXPECT_EQ("ok.", response_data);
7837}
7838
[email protected]65041fa2010-05-21 06:56:537839// This tests the case that a request is issued via http instead of spdy after
7840// npn is negotiated.
7841TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387842 HttpStreamFactory::set_use_alternate_protocols(true);
7843 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537844 SessionDependencies session_deps;
7845 HttpRequestInfo request;
7846 request.method = "GET";
7847 request.url = GURL("https://www.google.com/");
7848 request.load_flags = 0;
7849
7850 MockWrite data_writes[] = {
7851 MockWrite("GET / HTTP/1.1\r\n"
7852 "Host: www.google.com\r\n"
7853 "Connection: keep-alive\r\n\r\n"),
7854 };
7855
7856 MockRead data_reads[] = {
7857 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357858 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537859 MockRead("hello world"),
7860 MockRead(false, OK),
7861 };
7862
7863 SSLSocketDataProvider ssl(true, OK);
7864 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7865 ssl.next_proto = "http/1.1";
7866
7867 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7868
7869 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7870 data_writes, arraysize(data_writes));
7871 session_deps.socket_factory.AddSocketDataProvider(&data);
7872
7873 TestCompletionCallback callback;
7874
7875 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7876 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7877
7878 int rv = trans->Start(&request, &callback, BoundNetLog());
7879
7880 EXPECT_EQ(ERR_IO_PENDING, rv);
7881 EXPECT_EQ(OK, callback.WaitForResult());
7882
7883 const HttpResponseInfo* response = trans->GetResponseInfo();
7884 ASSERT_TRUE(response != NULL);
7885 ASSERT_TRUE(response->headers != NULL);
7886 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7887
7888 std::string response_data;
7889 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7890 EXPECT_EQ("hello world", response_data);
7891
7892 EXPECT_FALSE(response->was_fetched_via_spdy);
7893 EXPECT_TRUE(response->was_npn_negotiated);
7894
[email protected]8e6441ca2010-08-19 05:56:387895 HttpStreamFactory::set_next_protos("");
7896 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537897}
[email protected]26ef6582010-06-24 02:30:477898
7899TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7900 // Simulate the SSL handshake completing with an NPN negotiation
7901 // followed by an immediate server closing of the socket.
7902 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387903 HttpStreamFactory::set_use_alternate_protocols(true);
7904 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477905 SessionDependencies session_deps;
7906
7907 HttpRequestInfo request;
7908 request.method = "GET";
7909 request.url = GURL("https://www.google.com/");
7910 request.load_flags = 0;
7911
7912 SSLSocketDataProvider ssl(true, OK);
7913 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357914 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477915 ssl.was_npn_negotiated = true;
7916 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7917
[email protected]2bd93022010-07-17 00:58:447918 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137919 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477920
7921 MockRead spdy_reads[] = {
7922 MockRead(false, 0, 0) // Not async - return 0 immediately.
7923 };
7924
7925 scoped_refptr<DelayedSocketData> spdy_data(
7926 new DelayedSocketData(
7927 0, // don't wait in this case, immediate hangup.
7928 spdy_reads, arraysize(spdy_reads),
7929 spdy_writes, arraysize(spdy_writes)));
7930 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7931
7932 TestCompletionCallback callback;
7933
7934 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7935 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7936
7937 int rv = trans->Start(&request, &callback, BoundNetLog());
7938 EXPECT_EQ(ERR_IO_PENDING, rv);
7939 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7940
[email protected]8e6441ca2010-08-19 05:56:387941 HttpStreamFactory::set_next_protos("");
7942 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477943}
[email protected]65d34382010-07-01 18:12:267944
[email protected]f45c1ee2010-08-03 00:54:307945TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7946 // This test ensures that the URL passed into the proxy is upgraded
7947 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387948 HttpStreamFactory::set_use_alternate_protocols(true);
7949 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307950 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7951
[email protected]81cdfcd2010-10-16 00:49:007952 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307953 HttpAuthHandlerMock::Factory* auth_factory =
7954 new HttpAuthHandlerMock::Factory();
7955 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7956 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7957 auth_factory->set_do_init_from_challenge(true);
7958 session_deps.http_auth_handler_factory.reset(auth_factory);
7959
7960 HttpRequestInfo request;
7961 request.method = "GET";
7962 request.url = GURL("http://www.google.com");
7963 request.load_flags = 0;
7964
7965 // First round goes unauthenticated through the proxy.
7966 MockWrite data_writes_1[] = {
7967 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7968 "Host: www.google.com\r\n"
7969 "Proxy-Connection: keep-alive\r\n"
7970 "\r\n"),
7971 };
7972 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597973 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307974 MockRead("HTTP/1.1 200 OK\r\n"
7975 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7976 "Proxy-Connection: close\r\n"
7977 "\r\n"),
7978 };
7979 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7980 data_writes_1, arraysize(data_writes_1));
7981
7982 // Second round tries to tunnel to www.google.com due to the
7983 // Alternate-Protocol announcement in the first round. It fails due
7984 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597985 // After the failure, a tunnel is established to www.google.com using
7986 // Proxy-Authorization headers. There is then a SPDY request round.
7987 //
7988 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7989 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7990 // does a Disconnect and Connect on the same socket, rather than trying
7991 // to obtain a new one.
7992 //
7993 // NOTE: Originally, the proxy response to the second CONNECT request
7994 // simply returned another 407 so the unit test could skip the SSL connection
7995 // establishment and SPDY framing issues. Alas, the
7996 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307997 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597998
[email protected]f45c1ee2010-08-03 00:54:307999 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8000 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8001 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8002
[email protected]394816e92010-08-03 07:38:598003 MockWrite data_writes_2[] = {
8004 // First connection attempt without Proxy-Authorization.
8005 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8006 "Host: www.google.com\r\n"
8007 "Proxy-Connection: keep-alive\r\n"
8008 "\r\n"),
8009
8010 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308011 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8012 "Host: www.google.com\r\n"
8013 "Proxy-Connection: keep-alive\r\n"
8014 "Proxy-Authorization: auth_token\r\n"
8015 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308016
[email protected]394816e92010-08-03 07:38:598017 // SPDY request
8018 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308019 };
[email protected]394816e92010-08-03 07:38:598020 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8021 "Proxy-Authenticate: Mock\r\n"
8022 "Proxy-Connection: close\r\n"
8023 "\r\n");
8024 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8025 MockRead data_reads_2[] = {
8026 // First connection attempt fails
8027 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8028 MockRead(true, kRejectConnectResponse,
8029 arraysize(kRejectConnectResponse) - 1, 1),
8030
8031 // Second connection attempt passes
8032 MockRead(true, kAcceptConnectResponse,
8033 arraysize(kAcceptConnectResponse) -1, 4),
8034
8035 // SPDY response
8036 CreateMockRead(*resp.get(), 6),
8037 CreateMockRead(*data.get(), 6),
8038 MockRead(true, 0, 0, 6),
8039 };
8040 scoped_refptr<OrderedSocketData> data_2(
8041 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8042 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308043
8044 SSLSocketDataProvider ssl(true, OK);
8045 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8046 ssl.next_proto = "spdy/2";
8047 ssl.was_npn_negotiated = true;
8048
[email protected]2d6728692011-03-12 01:39:558049 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8050 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8051 NULL, 0, NULL, 0);
8052 hanging_non_alternate_protocol_socket.set_connect_data(
8053 never_finishing_connect);
8054
[email protected]f45c1ee2010-08-03 00:54:308055 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598056 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308057 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558058 session_deps.socket_factory.AddSocketDataProvider(
8059 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308060 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8061
8062 // First round should work and provide the Alternate-Protocol state.
8063 TestCompletionCallback callback_1;
8064 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8065 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8066 EXPECT_EQ(ERR_IO_PENDING, rv);
8067 EXPECT_EQ(OK, callback_1.WaitForResult());
8068
8069 // Second round should attempt a tunnel connect and get an auth challenge.
8070 TestCompletionCallback callback_2;
8071 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8072 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8073 EXPECT_EQ(ERR_IO_PENDING, rv);
8074 EXPECT_EQ(OK, callback_2.WaitForResult());
8075 const HttpResponseInfo* response = trans_2->GetResponseInfo();
8076 ASSERT_FALSE(response == NULL);
8077 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8078
8079 // Restart with auth. Tunnel should work and response received.
8080 TestCompletionCallback callback_3;
8081 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
8082 EXPECT_EQ(ERR_IO_PENDING, rv);
8083 EXPECT_EQ(OK, callback_3.WaitForResult());
8084
8085 // After all that work, these two lines (or actually, just the scheme) are
8086 // what this test is all about. Make sure it happens correctly.
8087 const GURL& request_url = auth_handler->request_url();
8088 EXPECT_EQ("https", request_url.scheme());
8089 EXPECT_EQ("www.google.com", request_url.host());
8090
[email protected]8e6441ca2010-08-19 05:56:388091 HttpStreamFactory::set_next_protos("");
8092 HttpStreamFactory::set_use_alternate_protocols(false);
8093}
8094
8095// Test that if we cancel the transaction as the connection is completing, that
8096// everything tears down correctly.
8097TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8098 // Setup everything about the connection to complete synchronously, so that
8099 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8100 // for is the callback from the HttpStreamRequest.
8101 // Then cancel the transaction.
8102 // Verify that we don't crash.
8103 MockConnect mock_connect(false, OK);
8104 MockRead data_reads[] = {
8105 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8106 MockRead(false, "hello world"),
8107 MockRead(false, OK),
8108 };
8109
[email protected]8e6441ca2010-08-19 05:56:388110 HttpRequestInfo request;
8111 request.method = "GET";
8112 request.url = GURL("http://www.google.com/");
8113 request.load_flags = 0;
8114
[email protected]cb9bf6ca2011-01-28 13:15:278115 SessionDependencies session_deps;
8116 session_deps.host_resolver->set_synchronous_mode(true);
8117 scoped_ptr<HttpTransaction> trans(
8118 new HttpNetworkTransaction(CreateSession(&session_deps)));
8119
[email protected]8e6441ca2010-08-19 05:56:388120 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8121 data.set_connect_data(mock_connect);
8122 session_deps.socket_factory.AddSocketDataProvider(&data);
8123
8124 TestCompletionCallback callback;
8125
8126 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8127 int rv = trans->Start(&request, &callback, log.bound());
8128 EXPECT_EQ(ERR_IO_PENDING, rv);
8129 trans.reset(); // Cancel the transaction here.
8130
8131 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308132}
8133
[email protected]76a505b2010-08-25 06:23:008134// Test a basic GET request through a proxy.
8135TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008136 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008137 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8138 session_deps.net_log = log.bound().net_log();
8139 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8140
[email protected]76a505b2010-08-25 06:23:008141 HttpRequestInfo request;
8142 request.method = "GET";
8143 request.url = GURL("http://www.google.com/");
8144
8145 MockWrite data_writes1[] = {
8146 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8147 "Host: www.google.com\r\n"
8148 "Proxy-Connection: keep-alive\r\n\r\n"),
8149 };
8150
8151 MockRead data_reads1[] = {
8152 MockRead("HTTP/1.1 200 OK\r\n"),
8153 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8154 MockRead("Content-Length: 100\r\n\r\n"),
8155 MockRead(false, OK),
8156 };
8157
8158 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8159 data_writes1, arraysize(data_writes1));
8160 session_deps.socket_factory.AddSocketDataProvider(&data1);
8161
8162 TestCompletionCallback callback1;
8163
[email protected]0b0bf032010-09-21 18:08:508164 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8165
[email protected]76a505b2010-08-25 06:23:008166 int rv = trans->Start(&request, &callback1, log.bound());
8167 EXPECT_EQ(ERR_IO_PENDING, rv);
8168
8169 rv = callback1.WaitForResult();
8170 EXPECT_EQ(OK, rv);
8171
8172 const HttpResponseInfo* response = trans->GetResponseInfo();
8173 ASSERT_FALSE(response == NULL);
8174
8175 EXPECT_TRUE(response->headers->IsKeepAlive());
8176 EXPECT_EQ(200, response->headers->response_code());
8177 EXPECT_EQ(100, response->headers->GetContentLength());
8178 EXPECT_TRUE(response->was_fetched_via_proxy);
8179 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8180}
8181
8182// Test a basic HTTPS GET request through a proxy.
8183TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008184 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008185 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8186 session_deps.net_log = log.bound().net_log();
8187 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8188
[email protected]76a505b2010-08-25 06:23:008189 HttpRequestInfo request;
8190 request.method = "GET";
8191 request.url = GURL("https://www.google.com/");
8192
8193 // Since we have proxy, should try to establish tunnel.
8194 MockWrite data_writes1[] = {
8195 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8196 "Host: www.google.com\r\n"
8197 "Proxy-Connection: keep-alive\r\n\r\n"),
8198
8199 MockWrite("GET / HTTP/1.1\r\n"
8200 "Host: www.google.com\r\n"
8201 "Connection: keep-alive\r\n\r\n"),
8202 };
8203
8204 MockRead data_reads1[] = {
8205 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8206
8207 MockRead("HTTP/1.1 200 OK\r\n"),
8208 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8209 MockRead("Content-Length: 100\r\n\r\n"),
8210 MockRead(false, OK),
8211 };
8212
8213 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8214 data_writes1, arraysize(data_writes1));
8215 session_deps.socket_factory.AddSocketDataProvider(&data1);
8216 SSLSocketDataProvider ssl(true, OK);
8217 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8218
8219 TestCompletionCallback callback1;
8220
[email protected]0b0bf032010-09-21 18:08:508221 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8222
[email protected]76a505b2010-08-25 06:23:008223 int rv = trans->Start(&request, &callback1, log.bound());
8224 EXPECT_EQ(ERR_IO_PENDING, rv);
8225
8226 rv = callback1.WaitForResult();
8227 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408228 net::CapturingNetLog::EntryList entries;
8229 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008230 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408231 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008232 NetLog::PHASE_NONE);
8233 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408234 entries, pos,
[email protected]76a505b2010-08-25 06:23:008235 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8236 NetLog::PHASE_NONE);
8237
8238 const HttpResponseInfo* response = trans->GetResponseInfo();
8239 ASSERT_FALSE(response == NULL);
8240
8241 EXPECT_TRUE(response->headers->IsKeepAlive());
8242 EXPECT_EQ(200, response->headers->response_code());
8243 EXPECT_EQ(100, response->headers->GetContentLength());
8244 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8245 EXPECT_TRUE(response->was_fetched_via_proxy);
8246}
8247
8248// Test a basic HTTPS GET request through a proxy, but the server hangs up
8249// while establishing the tunnel.
8250TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008251 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008252 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8253 session_deps.net_log = log.bound().net_log();
8254 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8255
[email protected]76a505b2010-08-25 06:23:008256 HttpRequestInfo request;
8257 request.method = "GET";
8258 request.url = GURL("https://www.google.com/");
8259
8260 // Since we have proxy, should try to establish tunnel.
8261 MockWrite data_writes1[] = {
8262 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8263 "Host: www.google.com\r\n"
8264 "Proxy-Connection: keep-alive\r\n\r\n"),
8265
8266 MockWrite("GET / HTTP/1.1\r\n"
8267 "Host: www.google.com\r\n"
8268 "Connection: keep-alive\r\n\r\n"),
8269 };
8270
8271 MockRead data_reads1[] = {
8272 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8273 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8274 MockRead(true, 0, 0), // EOF
8275 };
8276
8277 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8278 data_writes1, arraysize(data_writes1));
8279 session_deps.socket_factory.AddSocketDataProvider(&data1);
8280 SSLSocketDataProvider ssl(true, OK);
8281 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8282
8283 TestCompletionCallback callback1;
8284
[email protected]0b0bf032010-09-21 18:08:508285 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8286
[email protected]76a505b2010-08-25 06:23:008287 int rv = trans->Start(&request, &callback1, log.bound());
8288 EXPECT_EQ(ERR_IO_PENDING, rv);
8289
8290 rv = callback1.WaitForResult();
8291 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408292 net::CapturingNetLog::EntryList entries;
8293 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008294 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408295 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008296 NetLog::PHASE_NONE);
8297 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408298 entries, pos,
[email protected]76a505b2010-08-25 06:23:008299 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8300 NetLog::PHASE_NONE);
8301}
8302
[email protected]749eefa82010-09-13 22:14:038303// Test for crbug.com/55424.
8304TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8305 SessionDependencies session_deps;
8306
8307 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8308 "https://www.google.com", false, 1, LOWEST));
8309 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8310
8311 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8312 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8313 MockRead spdy_reads[] = {
8314 CreateMockRead(*resp),
8315 CreateMockRead(*data),
8316 MockRead(true, 0, 0),
8317 };
8318
8319 scoped_refptr<DelayedSocketData> spdy_data(
8320 new DelayedSocketData(
8321 1, // wait for one write to finish before reading.
8322 spdy_reads, arraysize(spdy_reads),
8323 spdy_writes, arraysize(spdy_writes)));
8324 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8325
8326 SSLSocketDataProvider ssl(true, OK);
8327 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8328 ssl.next_proto = "spdy/2";
8329 ssl.was_npn_negotiated = true;
8330 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8331
8332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8333
8334 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388335 HostPortPair host_port_pair("www.google.com", 443);
8336 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038337 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318338 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288339 scoped_refptr<TransportSocketParams> transport_params(
8340 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:388341 TestCompletionCallback callback;
8342
8343 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8344 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288345 connection->Init(host_port_pair.ToString(), transport_params,
8346 LOWEST, &callback,
8347 session->transport_socket_pool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388348 EXPECT_EQ(OK, callback.WaitForResult());
8349 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038350
8351 HttpRequestInfo request;
8352 request.method = "GET";
8353 request.url = GURL("https://www.google.com/");
8354 request.load_flags = 0;
8355
8356 // This is the important line that marks this as a preconnect.
8357 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8358
8359 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8360
[email protected]749eefa82010-09-13 22:14:038361 int rv = trans->Start(&request, &callback, BoundNetLog());
8362 EXPECT_EQ(ERR_IO_PENDING, rv);
8363 EXPECT_EQ(OK, callback.WaitForResult());
8364}
8365
[email protected]73b8dd222010-11-11 19:55:248366// Given a net error, cause that error to be returned from the first Write()
8367// call and verify that the HttpTransaction fails with that error.
8368static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278369 net::HttpRequestInfo request_info;
8370 request_info.url = GURL("https://www.example.com/");
8371 request_info.method = "GET";
8372 request_info.load_flags = net::LOAD_NORMAL;
8373
[email protected]73b8dd222010-11-11 19:55:248374 SessionDependencies session_deps;
8375
8376 SSLSocketDataProvider ssl_data(async, OK);
8377 net::MockWrite data_writes[] = {
8378 net::MockWrite(async, error),
8379 };
8380 net::StaticSocketDataProvider data(NULL, 0,
8381 data_writes, arraysize(data_writes));
8382 session_deps.socket_factory.AddSocketDataProvider(&data);
8383 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8384
8385 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8386 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8387
[email protected]73b8dd222010-11-11 19:55:248388 TestCompletionCallback callback;
8389 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8390 if (rv == net::ERR_IO_PENDING)
8391 rv = callback.WaitForResult();
8392 ASSERT_EQ(error, rv);
8393}
8394
8395TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8396 // Just check a grab bag of cert errors.
8397 static const int kErrors[] = {
8398 ERR_CERT_COMMON_NAME_INVALID,
8399 ERR_CERT_AUTHORITY_INVALID,
8400 ERR_CERT_DATE_INVALID,
8401 };
8402 for (size_t i = 0; i < arraysize(kErrors); i++) {
8403 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8404 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8405 }
8406}
8407
[email protected]bd0b6772011-01-11 19:59:308408// Ensure that a client certificate is removed from the SSL client auth
8409// cache when:
8410// 1) No proxy is involved.
8411// 2) TLS False Start is disabled.
8412// 3) The initial TLS handshake requests a client certificate.
8413// 4) The client supplies an invalid/unacceptable certificate.
8414TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278415 net::HttpRequestInfo request_info;
8416 request_info.url = GURL("https://www.example.com/");
8417 request_info.method = "GET";
8418 request_info.load_flags = net::LOAD_NORMAL;
8419
[email protected]bd0b6772011-01-11 19:59:308420 SessionDependencies session_deps;
8421
8422 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8423 cert_request->host_and_port = "www.example.com:443";
8424
8425 // [ssl_]data1 contains the data for the first SSL handshake. When a
8426 // CertificateRequest is received for the first time, the handshake will
8427 // be aborted to allow the caller to provide a certificate.
8428 SSLSocketDataProvider ssl_data1(true /* async */,
8429 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8430 ssl_data1.cert_request_info = cert_request.get();
8431 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8432 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8433 session_deps.socket_factory.AddSocketDataProvider(&data1);
8434
8435 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8436 // False Start is not being used, the result of the SSL handshake will be
8437 // returned as part of the SSLClientSocket::Connect() call. This test
8438 // matches the result of a server sending a handshake_failure alert,
8439 // rather than a Finished message, because it requires a client
8440 // certificate and none was supplied.
8441 SSLSocketDataProvider ssl_data2(true /* async */,
8442 net::ERR_SSL_PROTOCOL_ERROR);
8443 ssl_data2.cert_request_info = cert_request.get();
8444 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8445 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8446 session_deps.socket_factory.AddSocketDataProvider(&data2);
8447
8448 // [ssl_]data3 contains the data for the third SSL handshake. When a
8449 // connection to a server fails during an SSL handshake,
8450 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8451 // connection was attempted with TLSv1. This is transparent to the caller
8452 // of the HttpNetworkTransaction. Because this test failure is due to
8453 // requiring a client certificate, this fallback handshake should also
8454 // fail.
8455 SSLSocketDataProvider ssl_data3(true /* async */,
8456 net::ERR_SSL_PROTOCOL_ERROR);
8457 ssl_data3.cert_request_info = cert_request.get();
8458 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8459 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8460 session_deps.socket_factory.AddSocketDataProvider(&data3);
8461
8462 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8463 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8464
[email protected]bd0b6772011-01-11 19:59:308465 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8466 TestCompletionCallback callback;
8467 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8468 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8469
8470 // Complete the SSL handshake, which should abort due to requiring a
8471 // client certificate.
8472 rv = callback.WaitForResult();
8473 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8474
8475 // Indicate that no certificate should be supplied. From the perspective
8476 // of SSLClientCertCache, NULL is just as meaningful as a real
8477 // certificate, so this is the same as supply a
8478 // legitimate-but-unacceptable certificate.
8479 rv = trans->RestartWithCertificate(NULL, &callback);
8480 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8481
8482 // Ensure the certificate was added to the client auth cache before
8483 // allowing the connection to continue restarting.
8484 scoped_refptr<X509Certificate> client_cert;
8485 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8486 &client_cert));
8487 ASSERT_EQ(NULL, client_cert.get());
8488
8489 // Restart the handshake. This will consume ssl_data2, which fails, and
8490 // then consume ssl_data3, which should also fail. The result code is
8491 // checked against what ssl_data3 should return.
8492 rv = callback.WaitForResult();
8493 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8494
8495 // Ensure that the client certificate is removed from the cache on a
8496 // handshake failure.
8497 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8498 &client_cert));
8499}
8500
8501// Ensure that a client certificate is removed from the SSL client auth
8502// cache when:
8503// 1) No proxy is involved.
8504// 2) TLS False Start is enabled.
8505// 3) The initial TLS handshake requests a client certificate.
8506// 4) The client supplies an invalid/unacceptable certificate.
8507TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278508 net::HttpRequestInfo request_info;
8509 request_info.url = GURL("https://www.example.com/");
8510 request_info.method = "GET";
8511 request_info.load_flags = net::LOAD_NORMAL;
8512
[email protected]bd0b6772011-01-11 19:59:308513 SessionDependencies session_deps;
8514
8515 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8516 cert_request->host_and_port = "www.example.com:443";
8517
8518 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8519 // return successfully after reading up to the peer's Certificate message.
8520 // This is to allow the caller to call SSLClientSocket::Write(), which can
8521 // enqueue application data to be sent in the same packet as the
8522 // ChangeCipherSpec and Finished messages.
8523 // The actual handshake will be finished when SSLClientSocket::Read() is
8524 // called, which expects to process the peer's ChangeCipherSpec and
8525 // Finished messages. If there was an error negotiating with the peer,
8526 // such as due to the peer requiring a client certificate when none was
8527 // supplied, the alert sent by the peer won't be processed until Read() is
8528 // called.
8529
8530 // Like the non-False Start case, when a client certificate is requested by
8531 // the peer, the handshake is aborted during the Connect() call.
8532 // [ssl_]data1 represents the initial SSL handshake with the peer.
8533 SSLSocketDataProvider ssl_data1(true /* async */,
8534 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8535 ssl_data1.cert_request_info = cert_request.get();
8536 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8537 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8538 session_deps.socket_factory.AddSocketDataProvider(&data1);
8539
8540 // When a client certificate is supplied, Connect() will not be aborted
8541 // when the peer requests the certificate. Instead, the handshake will
8542 // artificially succeed, allowing the caller to write the HTTP request to
8543 // the socket. The handshake messages are not processed until Read() is
8544 // called, which then detects that the handshake was aborted, due to the
8545 // peer sending a handshake_failure because it requires a client
8546 // certificate.
8547 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8548 ssl_data2.cert_request_info = cert_request.get();
8549 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8550 net::MockRead data2_reads[] = {
8551 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8552 };
8553 net::StaticSocketDataProvider data2(
8554 data2_reads, arraysize(data2_reads), NULL, 0);
8555 session_deps.socket_factory.AddSocketDataProvider(&data2);
8556
8557 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8558 // the data for the SSL handshake once the TLSv1 connection falls back to
8559 // SSLv3. It has the same behaviour as [ssl_]data2.
8560 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8561 ssl_data3.cert_request_info = cert_request.get();
8562 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8563 net::StaticSocketDataProvider data3(
8564 data2_reads, arraysize(data2_reads), NULL, 0);
8565 session_deps.socket_factory.AddSocketDataProvider(&data3);
8566
8567 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8568 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8569
[email protected]bd0b6772011-01-11 19:59:308570 // Begin the initial SSL handshake.
8571 TestCompletionCallback callback;
8572 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8573 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8574
8575 // Complete the SSL handshake, which should abort due to requiring a
8576 // client certificate.
8577 rv = callback.WaitForResult();
8578 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8579
8580 // Indicate that no certificate should be supplied. From the perspective
8581 // of SSLClientCertCache, NULL is just as meaningful as a real
8582 // certificate, so this is the same as supply a
8583 // legitimate-but-unacceptable certificate.
8584 rv = trans->RestartWithCertificate(NULL, &callback);
8585 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8586
8587 // Ensure the certificate was added to the client auth cache before
8588 // allowing the connection to continue restarting.
8589 scoped_refptr<X509Certificate> client_cert;
8590 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8591 &client_cert));
8592 ASSERT_EQ(NULL, client_cert.get());
8593
8594
8595 // Restart the handshake. This will consume ssl_data2, which fails, and
8596 // then consume ssl_data3, which should also fail. The result code is
8597 // checked against what ssl_data3 should return.
8598 rv = callback.WaitForResult();
8599 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8600
8601 // Ensure that the client certificate is removed from the cache on a
8602 // handshake failure.
8603 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8604 &client_cert));
8605}
8606
[email protected]8c405132011-01-11 22:03:188607// Ensure that a client certificate is removed from the SSL client auth
8608// cache when:
8609// 1) An HTTPS proxy is involved.
8610// 3) The HTTPS proxy requests a client certificate.
8611// 4) The client supplies an invalid/unacceptable certificate for the
8612// proxy.
8613// The test is repeated twice, first for connecting to an HTTPS endpoint,
8614// then for connecting to an HTTP endpoint.
8615TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8616 SessionDependencies session_deps(
8617 ProxyService::CreateFixed("https://proxy:70"));
8618 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8619 session_deps.net_log = log.bound().net_log();
8620
8621 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8622 cert_request->host_and_port = "proxy:70";
8623
8624 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8625 // [ssl_]data[1-3]. Rather than represending the endpoint
8626 // (www.example.com:443), they represent failures with the HTTPS proxy
8627 // (proxy:70).
8628 SSLSocketDataProvider ssl_data1(true /* async */,
8629 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8630 ssl_data1.cert_request_info = cert_request.get();
8631 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8632 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8633 session_deps.socket_factory.AddSocketDataProvider(&data1);
8634
8635 SSLSocketDataProvider ssl_data2(true /* async */,
8636 net::ERR_SSL_PROTOCOL_ERROR);
8637 ssl_data2.cert_request_info = cert_request.get();
8638 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8639 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8640 session_deps.socket_factory.AddSocketDataProvider(&data2);
8641
8642 SSLSocketDataProvider ssl_data3(true /* async */,
8643 net::ERR_SSL_PROTOCOL_ERROR);
8644 ssl_data3.cert_request_info = cert_request.get();
8645 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8646 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8647 session_deps.socket_factory.AddSocketDataProvider(&data3);
8648
8649 net::HttpRequestInfo requests[2];
8650 requests[0].url = GURL("https://www.example.com/");
8651 requests[0].method = "GET";
8652 requests[0].load_flags = net::LOAD_NORMAL;
8653
8654 requests[1].url = GURL("http://www.example.com/");
8655 requests[1].method = "GET";
8656 requests[1].load_flags = net::LOAD_NORMAL;
8657
8658 for (size_t i = 0; i < arraysize(requests); ++i) {
8659 session_deps.socket_factory.ResetNextMockIndexes();
8660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8661 scoped_ptr<HttpNetworkTransaction> trans(
8662 new HttpNetworkTransaction(session));
8663
8664 // Begin the SSL handshake with the proxy.
8665 TestCompletionCallback callback;
8666 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8667 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8668
8669 // Complete the SSL handshake, which should abort due to requiring a
8670 // client certificate.
8671 rv = callback.WaitForResult();
8672 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8673
8674 // Indicate that no certificate should be supplied. From the perspective
8675 // of SSLClientCertCache, NULL is just as meaningful as a real
8676 // certificate, so this is the same as supply a
8677 // legitimate-but-unacceptable certificate.
8678 rv = trans->RestartWithCertificate(NULL, &callback);
8679 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8680
8681 // Ensure the certificate was added to the client auth cache before
8682 // allowing the connection to continue restarting.
8683 scoped_refptr<X509Certificate> client_cert;
8684 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8685 &client_cert));
8686 ASSERT_EQ(NULL, client_cert.get());
8687 // Ensure the certificate was NOT cached for the endpoint. This only
8688 // applies to HTTPS requests, but is fine to check for HTTP requests.
8689 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8690 &client_cert));
8691
8692 // Restart the handshake. This will consume ssl_data2, which fails, and
8693 // then consume ssl_data3, which should also fail. The result code is
8694 // checked against what ssl_data3 should return.
8695 rv = callback.WaitForResult();
8696 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8697
8698 // Now that the new handshake has failed, ensure that the client
8699 // certificate was removed from the client auth cache.
8700 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8701 &client_cert));
8702 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8703 &client_cert));
8704 }
8705}
8706
[email protected]5c288bc2011-07-26 15:12:058707void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8708 SpdySessionPoolPeer* pool_peer,
8709 std::string host,
8710 int port,
8711 std::string iplist) {
8712 // Create a host resolver dependency that returns address |iplist| for
8713 // resolutions of |host|.
8714 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:048715
[email protected]5c288bc2011-07-26 15:12:058716 // Setup a HostPortProxyPair.
8717 HostPortPair host_port_pair(host, port);
8718 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
8719 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:048720
[email protected]5c288bc2011-07-26 15:12:058721 // Resolve the host and port.
8722 AddressList addresses;
8723 HostResolver::RequestInfo info(host_port_pair);
8724 host_resolver->Resolve(info, &addresses, NULL, NULL, BoundNetLog());
[email protected]46da33be2011-07-19 21:58:048725
[email protected]5c288bc2011-07-26 15:12:058726 // Add the first address as an alias. It would have been better to call
8727 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
8728 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
8729 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
8730 // the |pair|.
8731 const addrinfo* address = addresses.head();
8732 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:048733}
8734
[email protected]e3ceb682011-06-28 23:55:468735TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
8736 HttpStreamFactory::set_use_alternate_protocols(true);
8737 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]e3ceb682011-06-28 23:55:468738
8739 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
8740 SessionDependencies session_deps;
8741 MockCachingHostResolver host_resolver;
8742 net::HttpNetworkSession::Params params;
8743 params.client_socket_factory = &session_deps.socket_factory;
8744 params.host_resolver = &host_resolver;
8745 params.cert_verifier = session_deps.cert_verifier.get();
8746 params.proxy_service = session_deps.proxy_service.get();
8747 params.ssl_config_service = session_deps.ssl_config_service;
8748 params.http_auth_handler_factory =
8749 session_deps.http_auth_handler_factory.get();
8750 params.net_log = session_deps.net_log;
8751 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268752 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8753 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468754
8755 SSLSocketDataProvider ssl(true, OK);
8756 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8757 ssl.next_proto = "spdy/2";
8758 ssl.was_npn_negotiated = true;
8759 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8760
8761 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8762 "https://www.google.com", false, 1, LOWEST));
8763 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8764 "https://www.gmail.com", false, 3, LOWEST));
8765 MockWrite spdy_writes[] = {
8766 CreateMockWrite(*host1_req, 1),
8767 CreateMockWrite(*host2_req, 4),
8768 };
8769 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8770 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8771 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8772 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8773 MockRead spdy_reads[] = {
8774 CreateMockRead(*host1_resp, 2),
8775 CreateMockRead(*host1_resp_body, 3),
8776 CreateMockRead(*host2_resp, 5),
8777 CreateMockRead(*host2_resp_body, 6),
8778 MockRead(true, 0, 7),
8779 };
8780
8781 scoped_refptr<OrderedSocketData> spdy_data(
8782 new OrderedSocketData(
8783 spdy_reads, arraysize(spdy_reads),
8784 spdy_writes, arraysize(spdy_writes)));
8785 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8786
8787 TestCompletionCallback callback;
8788 HttpRequestInfo request1;
8789 request1.method = "GET";
8790 request1.url = GURL("https://www.google.com/");
8791 request1.load_flags = 0;
8792 HttpNetworkTransaction trans1(session);
8793
8794 int rv = trans1.Start(&request1, &callback, BoundNetLog());
8795 EXPECT_EQ(ERR_IO_PENDING, rv);
8796 EXPECT_EQ(OK, callback.WaitForResult());
8797
8798 const HttpResponseInfo* response = trans1.GetResponseInfo();
8799 ASSERT_TRUE(response != NULL);
8800 ASSERT_TRUE(response->headers != NULL);
8801 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8802
8803 std::string response_data;
8804 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8805 EXPECT_EQ("hello!", response_data);
8806
8807 // Preload www.gmail.com into HostCache.
8808 HostPortPair host_port("www.gmail.com", 443);
8809 HostResolver::RequestInfo resolve_info(host_port);
8810 AddressList ignored;
8811 host_resolver.Resolve(resolve_info, &ignored, NULL, NULL, BoundNetLog());
8812
[email protected]5c288bc2011-07-26 15:12:058813 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
8814 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
8815 // (www.google.com, 443).
8816 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
8817 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:048818
[email protected]e3ceb682011-06-28 23:55:468819 HttpRequestInfo request2;
8820 request2.method = "GET";
8821 request2.url = GURL("https://www.gmail.com/");
8822 request2.load_flags = 0;
8823 HttpNetworkTransaction trans2(session);
8824
8825 rv = trans2.Start(&request2, &callback, BoundNetLog());
8826 EXPECT_EQ(ERR_IO_PENDING, rv);
8827 EXPECT_EQ(OK, callback.WaitForResult());
8828
8829 response = trans2.GetResponseInfo();
8830 ASSERT_TRUE(response != NULL);
8831 ASSERT_TRUE(response->headers != NULL);
8832 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8833 EXPECT_TRUE(response->was_fetched_via_spdy);
8834 EXPECT_TRUE(response->was_npn_negotiated);
8835 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8836 EXPECT_EQ("hello!", response_data);
8837
8838 HttpStreamFactory::set_next_protos("");
8839 HttpStreamFactory::set_use_alternate_protocols(false);
8840}
8841
8842class OneTimeCachingHostResolver : public net::HostResolver {
8843 public:
8844 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
8845 : host_port_(host_port) {}
8846 virtual ~OneTimeCachingHostResolver() {}
8847
8848 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
8849
8850 // HostResolver methods:
8851 virtual int Resolve(const RequestInfo& info,
8852 AddressList* addresses,
8853 CompletionCallback* callback,
8854 RequestHandle* out_req,
8855 const BoundNetLog& net_log) {
8856 int rv = host_resolver_.Resolve(
8857 info, addresses, callback, out_req, net_log);
8858 if (rv == OK && info.only_use_cached_response() &&
8859 info.host_port_pair().Equals(host_port_)) {
8860 // Discard cache.
8861 host_resolver_.Reset(NULL);
8862 }
8863 return rv;
8864 }
8865
8866 virtual void CancelRequest(RequestHandle req) {
8867 host_resolver_.CancelRequest(req);
8868 }
8869
8870 virtual void AddObserver(Observer* observer) {
8871 return host_resolver_.AddObserver(observer);
8872 }
8873
8874 virtual void RemoveObserver(Observer* observer) {
8875 return host_resolver_.RemoveObserver(observer);
8876 }
8877
[email protected]46da33be2011-07-19 21:58:048878 MockCachingHostResolver* GetMockHostResolver() {
8879 return &host_resolver_;
8880 }
8881
[email protected]e3ceb682011-06-28 23:55:468882 private:
8883 MockCachingHostResolver host_resolver_;
8884 const HostPortPair host_port_;
8885};
8886
8887TEST_F(HttpNetworkTransactionTest,
8888 UseIPConnectionPoolingWithHostCacheExpiration) {
8889 HttpStreamFactory::set_use_alternate_protocols(true);
8890 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]e3ceb682011-06-28 23:55:468891
8892 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
8893 SessionDependencies session_deps;
8894 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
8895 net::HttpNetworkSession::Params params;
8896 params.client_socket_factory = &session_deps.socket_factory;
8897 params.host_resolver = &host_resolver;
8898 params.cert_verifier = session_deps.cert_verifier.get();
8899 params.proxy_service = session_deps.proxy_service.get();
8900 params.ssl_config_service = session_deps.ssl_config_service;
8901 params.http_auth_handler_factory =
8902 session_deps.http_auth_handler_factory.get();
8903 params.net_log = session_deps.net_log;
8904 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268905 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8906 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468907
8908 SSLSocketDataProvider ssl(true, OK);
8909 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8910 ssl.next_proto = "spdy/2";
8911 ssl.was_npn_negotiated = true;
8912 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8913
8914 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8915 "https://www.google.com", false, 1, LOWEST));
8916 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8917 "https://www.gmail.com", false, 3, LOWEST));
8918 MockWrite spdy_writes[] = {
8919 CreateMockWrite(*host1_req, 1),
8920 CreateMockWrite(*host2_req, 4),
8921 };
8922 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8923 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8924 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8925 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8926 MockRead spdy_reads[] = {
8927 CreateMockRead(*host1_resp, 2),
8928 CreateMockRead(*host1_resp_body, 3),
8929 CreateMockRead(*host2_resp, 5),
8930 CreateMockRead(*host2_resp_body, 6),
8931 MockRead(true, 0, 7),
8932 };
8933
8934 scoped_refptr<OrderedSocketData> spdy_data(
8935 new OrderedSocketData(
8936 spdy_reads, arraysize(spdy_reads),
8937 spdy_writes, arraysize(spdy_writes)));
8938 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8939
8940 TestCompletionCallback callback;
8941 HttpRequestInfo request1;
8942 request1.method = "GET";
8943 request1.url = GURL("https://www.google.com/");
8944 request1.load_flags = 0;
8945 HttpNetworkTransaction trans1(session);
8946
8947 int rv = trans1.Start(&request1, &callback, BoundNetLog());
8948 EXPECT_EQ(ERR_IO_PENDING, rv);
8949 EXPECT_EQ(OK, callback.WaitForResult());
8950
8951 const HttpResponseInfo* response = trans1.GetResponseInfo();
8952 ASSERT_TRUE(response != NULL);
8953 ASSERT_TRUE(response->headers != NULL);
8954 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8955
8956 std::string response_data;
8957 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8958 EXPECT_EQ("hello!", response_data);
8959
8960 // Preload cache entries into HostCache.
8961 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
8962 AddressList ignored;
8963 host_resolver.Resolve(resolve_info, &ignored, NULL, NULL, BoundNetLog());
8964
8965 HttpRequestInfo request2;
8966 request2.method = "GET";
8967 request2.url = GURL("https://www.gmail.com/");
8968 request2.load_flags = 0;
8969 HttpNetworkTransaction trans2(session);
8970
[email protected]5c288bc2011-07-26 15:12:058971 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
8972 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
8973 // (www.google.com, 443).
8974 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
8975 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:048976
[email protected]e3ceb682011-06-28 23:55:468977 rv = trans2.Start(&request2, &callback, BoundNetLog());
8978 EXPECT_EQ(ERR_IO_PENDING, rv);
8979 EXPECT_EQ(OK, callback.WaitForResult());
8980
8981 response = trans2.GetResponseInfo();
8982 ASSERT_TRUE(response != NULL);
8983 ASSERT_TRUE(response->headers != NULL);
8984 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8985 EXPECT_TRUE(response->was_fetched_via_spdy);
8986 EXPECT_TRUE(response->was_npn_negotiated);
8987 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
8988 EXPECT_EQ("hello!", response_data);
8989
8990 HttpStreamFactory::set_next_protos("");
8991 HttpStreamFactory::set_use_alternate_protocols(false);
8992}
8993
[email protected]89ceba9a2009-03-21 03:46:068994} // namespace net