blob: 2af99c264c3d347abe95d40d09855df40f2d3aee [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]5285d972011-10-18 18:56:348#include <stdarg.h>
9#include <string>
[email protected]95d88ffe2010-02-04 21:25:3310#include <vector>
[email protected]77848d12008-11-14 00:00:2211
[email protected]2d731a32010-04-29 01:04:0612#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3013#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3314#include "base/file_path.h"
15#include "base/file_util.h"
[email protected]3b63f8f42011-03-28 01:54:1516#include "base/memory/scoped_ptr.h"
[email protected]5e6efa52011-06-27 17:26:4117#include "base/metrics/histogram.h"
[email protected]f36a8132011-09-02 18:36:3318#include "base/test/test_file_util.h"
[email protected]be1ce6a72010-08-03 14:35:2219#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3520#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1221#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3322#include "net/base/completion_callback.h"
[email protected]98e1cd012011-11-08 15:33:0923#include "net/base/host_cache.h"
[email protected]b59ff372009-07-15 22:04:3224#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1225#include "net/base/net_log.h"
26#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3127#include "net/base/request_priority.h"
[email protected]bd0b6772011-01-11 19:59:3028#include "net/base/ssl_cert_request_info.h"
[email protected]db36938c2009-08-19 21:48:4229#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3330#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/base/test_completion_callback.h"
32#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1233#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0034#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2935#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5736#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4037#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5238#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5639#include "net/http/http_network_session_peer.h"
[email protected]17291a022011-10-10 07:32:5340#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5741#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3842#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5243#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5344#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1145#include "net/proxy/proxy_resolver.h"
46#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4447#include "net/socket/client_socket_factory.h"
48#include "net/socket/socket_test_util.h"
49#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5450#include "net/spdy/spdy_framer.h"
51#include "net/spdy/spdy_session.h"
52#include "net/spdy/spdy_session_pool.h"
53#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5254#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1555#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5256
57//-----------------------------------------------------------------------------
58
[email protected]13c8a092010-07-29 06:15:4459namespace {
60
61const string16 kBar(ASCIIToUTF16("bar"));
62const string16 kBar2(ASCIIToUTF16("bar2"));
63const string16 kBar3(ASCIIToUTF16("bar3"));
64const string16 kBaz(ASCIIToUTF16("baz"));
65const string16 kFirst(ASCIIToUTF16("first"));
66const string16 kFoo(ASCIIToUTF16("foo"));
67const string16 kFoo2(ASCIIToUTF16("foo2"));
68const string16 kFoo3(ASCIIToUTF16("foo3"));
69const string16 kFou(ASCIIToUTF16("fou"));
70const string16 kSecond(ASCIIToUTF16("second"));
71const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
72const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
73
[email protected]5285d972011-10-18 18:56:3474// MakeNextProtos is a utility function that returns a vector of std::strings
75// from its arguments. Don't forget to terminate the argument list with a NULL.
76std::vector<std::string> MakeNextProtos(const char* a, ...) {
77 std::vector<std::string> ret;
78 ret.push_back(a);
79
80 va_list args;
81 va_start(args, a);
82
83 for (;;) {
84 const char* value = va_arg(args, const char*);
85 if (value == NULL)
86 break;
87 ret.push_back(value);
88 }
89 va_end(args);
90
91 return ret;
92}
93
94// SpdyNextProtos returns a vector of NPN protocol strings for negotiating
95// SPDY.
96std::vector<std::string> SpdyNextProtos() {
97 return MakeNextProtos("http/1.1", "spdy/2", NULL);
98}
99
[email protected]13c8a092010-07-29 06:15:44100} // namespace
101
[email protected]89ceba9a2009-03-21 03:46:06102namespace net {
103
[email protected]e44de5d2009-06-05 20:12:45104// Helper to manage the lifetimes of the dependencies for a
105// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44106struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59107 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42108 SessionDependencies()
109 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:15110 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:02111 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:10112 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08113 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:54114 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:54115 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59116
117 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45118 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42119 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:15120 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:42121 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10122 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08123 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:54124 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:54125 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59126
[email protected]73c45322010-10-01 23:57:54127 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:15128 scoped_ptr<CertVerifier> cert_verifier;
[email protected]6104ea5d2011-04-27 21:37:12129 scoped_ptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42130 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59131 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50132 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]17291a022011-10-10 07:32:53133 HttpServerPropertiesImpl http_server_properties;
[email protected]a7ea8832010-07-12 17:54:54134 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59135};
136
[email protected]228ff742009-06-05 01:19:59137HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]9e1bdd32011-02-03 21:48:34138 net::HttpNetworkSession::Params params;
139 params.client_socket_factory = &session_deps->socket_factory;
140 params.host_resolver = session_deps->host_resolver.get();
141 params.cert_verifier = session_deps->cert_verifier.get();
[email protected]6104ea5d2011-04-27 21:37:12142 params.proxy_service = session_deps->proxy_service.get();
[email protected]9e1bdd32011-02-03 21:48:34143 params.ssl_config_service = session_deps->ssl_config_service;
144 params.http_auth_handler_factory =
145 session_deps->http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:53146 params.http_server_properties = &session_deps->http_server_properties;
[email protected]9e1bdd32011-02-03 21:48:34147 params.net_log = session_deps->net_log;
148 return new HttpNetworkSession(params);
[email protected]e8d536192008-10-17 22:21:14149}
150
[email protected]89836e22008-09-25 20:33:42151class HttpNetworkTransactionTest : public PlatformTest {
[email protected]e3ceb682011-06-28 23:55:46152 protected:
153 struct SimpleGetHelperResult {
154 int rv;
155 std::string status_line;
156 std::string response_data;
157 };
158
[email protected]2ff8b312010-04-26 22:20:54159 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50160 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
161 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54162 spdy::SpdyFramer::set_enable_compression_default(false);
163 }
164
[email protected]0e75a732008-10-16 20:36:09165 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50166 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
167 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54168 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09169 // Empty the current queue.
170 MessageLoop::current()->RunAllPending();
171 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50172 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
173 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09174 }
175
[email protected]3d2a59b2008-09-26 19:44:25176 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52177
[email protected]5a60c8b2011-10-19 20:14:29178 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
179 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15180 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52181
[email protected]ff007e162009-05-23 09:13:15182 HttpRequestInfo request;
183 request.method = "GET";
184 request.url = GURL("http://www.google.com/");
185 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52186
[email protected]cb9bf6ca2011-01-28 13:15:27187 SessionDependencies session_deps;
188 scoped_ptr<HttpTransaction> trans(
189 new HttpNetworkTransaction(CreateSession(&session_deps)));
190
[email protected]5a60c8b2011-10-19 20:14:29191 for (size_t i = 0; i < data_count; ++i) {
192 session_deps.socket_factory.AddSocketDataProvider(data[i]);
193 }
initial.commit586acc5fe2008-07-26 22:42:52194
[email protected]f1f3f0f82011-10-01 20:38:10195 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52196
[email protected]169d0012010-05-10 23:20:12197 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40198 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12199 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15200 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52201
[email protected]ff007e162009-05-23 09:13:15202 out.rv = callback.WaitForResult();
203 if (out.rv != OK)
204 return out;
205
206 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50207 // Can't use ASSERT_* inside helper functions like this, so
208 // return an error.
209 if (response == NULL || response->headers == NULL) {
210 out.rv = ERR_UNEXPECTED;
211 return out;
212 }
[email protected]ff007e162009-05-23 09:13:15213 out.status_line = response->headers->GetStatusLine();
214
[email protected]6d81b482011-02-22 19:47:19215 EXPECT_EQ("192.0.2.33", response->socket_address.host());
216 EXPECT_EQ(0, response->socket_address.port());
217
[email protected]ff007e162009-05-23 09:13:15218 rv = ReadTransaction(trans.get(), &out.response_data);
219 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40220
221 net::CapturingNetLog::EntryList entries;
222 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39223 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40224 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12225 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39226 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40227 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39228 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
229 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15230
[email protected]b2fcd0e2010-12-01 15:19:40231 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40232 NetLogHttpRequestParameter* request_params =
233 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
234 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
235 EXPECT_EQ("Host: www.google.com\r\n"
236 "Connection: keep-alive\r\n\r\n",
237 request_params->GetHeaders().ToString());
238
[email protected]aecfbf22008-10-16 02:02:47239 return out;
[email protected]ff007e162009-05-23 09:13:15240 }
initial.commit586acc5fe2008-07-26 22:42:52241
[email protected]5a60c8b2011-10-19 20:14:29242 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
243 size_t reads_count) {
244 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
245 StaticSocketDataProvider* data[] = { &reads };
246 return SimpleGetHelperForData(data, 1);
247 }
248
[email protected]ff007e162009-05-23 09:13:15249 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
250 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52251
[email protected]ff007e162009-05-23 09:13:15252 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15253};
[email protected]231d5a32008-09-13 00:45:27254
[email protected]15a5ccf82008-10-23 19:57:43255// Fill |str| with a long header list that consumes >= |size| bytes.
256void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19257 const char* row =
258 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
259 const int sizeof_row = strlen(row);
260 const int num_rows = static_cast<int>(
261 ceil(static_cast<float>(size) / sizeof_row));
262 const int sizeof_data = num_rows * sizeof_row;
263 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43264 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51265
[email protected]4ddaf2502008-10-23 18:26:19266 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43267 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19268}
269
[email protected]385a4672009-03-11 22:21:29270// Alternative functions that eliminate randomness and dependency on the local
271// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20272void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29273 static const uint8 bytes[] = {
274 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
275 };
276 static size_t current_byte = 0;
277 for (size_t i = 0; i < n; ++i) {
278 output[i] = bytes[current_byte++];
279 current_byte %= arraysize(bytes);
280 }
281}
282
[email protected]fe2bc6a2009-03-23 16:52:20283void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29284 static const uint8 bytes[] = {
285 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
286 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
287 };
288 static size_t current_byte = 0;
289 for (size_t i = 0; i < n; ++i) {
290 output[i] = bytes[current_byte++];
291 current_byte %= arraysize(bytes);
292 }
293}
294
[email protected]fe2bc6a2009-03-23 16:52:20295std::string MockGetHostName() {
296 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29297}
298
[email protected]e60e47a2010-07-14 03:37:18299template<typename ParentPool>
300class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31301 public:
[email protected]9e1bdd32011-02-03 21:48:34302 CaptureGroupNameSocketPool(HostResolver* host_resolver,
303 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18304
[email protected]d80a4322009-08-14 07:07:49305 const std::string last_group_name_received() const {
306 return last_group_name_;
307 }
308
[email protected]684970b2009-08-14 04:54:46309 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49310 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31311 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31312 ClientSocketHandle* handle,
[email protected]f1f3f0f82011-10-01 20:38:10313 OldCompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53314 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31315 last_group_name_ = group_name;
316 return ERR_IO_PENDING;
317 }
[email protected]04e5be32009-06-26 20:00:31318 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21319 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31320 virtual void ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10321 StreamSocket* socket,
[email protected]9f95c692011-02-11 19:20:19322 int id) {}
[email protected]04e5be32009-06-26 20:00:31323 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31324 virtual int IdleSocketCount() const {
325 return 0;
326 }
327 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
328 return 0;
329 }
330 virtual LoadState GetLoadState(const std::string& group_name,
331 const ClientSocketHandle* handle) const {
332 return LOAD_STATE_IDLE;
333 }
[email protected]a796bcec2010-03-22 17:17:26334 virtual base::TimeDelta ConnectionTimeout() const {
335 return base::TimeDelta();
336 }
[email protected]d80a4322009-08-14 07:07:49337
338 private:
[email protected]04e5be32009-06-26 20:00:31339 std::string last_group_name_;
340};
341
[email protected]ab739042011-04-07 15:22:28342typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
343CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13344typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
345CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06346typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11347CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18348typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
349CaptureGroupNameSSLSocketPool;
350
351template<typename ParentPool>
352CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34353 HostResolver* host_resolver,
354 CertVerifier* /* cert_verifier */)
355 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18356
357template<>
[email protected]2df19bb2010-08-25 20:13:46358CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34359 HostResolver* host_resolver,
360 CertVerifier* /* cert_verifier */)
361 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
[email protected]2df19bb2010-08-25 20:13:46362
363template<>
[email protected]e60e47a2010-07-14 03:37:18364CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34365 HostResolver* host_resolver,
366 CertVerifier* cert_verifier)
367 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
[email protected]feb79bcd2011-07-21 16:55:17368 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11369
[email protected]231d5a32008-09-13 00:45:27370//-----------------------------------------------------------------------------
371
[email protected]dae22c52010-07-30 02:16:35372// This is the expected return from a current server advertising SPDY.
373static const char kAlternateProtocolHttpHeader[] =
374 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
375
[email protected]79cb5c12011-09-12 13:12:04376// Helper functions for validating that AuthChallengeInfo's are correctly
377// configured for common cases.
378bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
379 if (!auth_challenge)
380 return false;
381 EXPECT_FALSE(auth_challenge->is_proxy);
382 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
383 EXPECT_EQ("MyRealm1", auth_challenge->realm);
384 EXPECT_EQ("basic", auth_challenge->scheme);
385 return true;
386}
387
388bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
389 if (!auth_challenge)
390 return false;
391 EXPECT_TRUE(auth_challenge->is_proxy);
392 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
393 EXPECT_EQ("MyRealm1", auth_challenge->realm);
394 EXPECT_EQ("basic", auth_challenge->scheme);
395 return true;
396}
397
398bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
399 if (!auth_challenge)
400 return false;
401 EXPECT_FALSE(auth_challenge->is_proxy);
402 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
403 EXPECT_EQ("digestive", auth_challenge->realm);
404 EXPECT_EQ("digest", auth_challenge->scheme);
405 return true;
406}
407
408bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
409 if (!auth_challenge)
410 return false;
411 EXPECT_FALSE(auth_challenge->is_proxy);
412 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
413 EXPECT_EQ(std::string(), auth_challenge->realm);
414 EXPECT_EQ("ntlm", auth_challenge->scheme);
415 return true;
416}
417
[email protected]231d5a32008-09-13 00:45:27418TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59419 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40420 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43421 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27422}
423
424TEST_F(HttpNetworkTransactionTest, SimpleGET) {
425 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35426 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
427 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42428 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27429 };
[email protected]31a2bfe2010-02-09 08:03:39430 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
431 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42432 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27433 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
434 EXPECT_EQ("hello world", out.response_data);
435}
436
437// Response with no status line.
438TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
439 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35440 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42441 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27442 };
[email protected]31a2bfe2010-02-09 08:03:39443 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
444 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42445 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27446 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
447 EXPECT_EQ("hello world", out.response_data);
448}
449
450// Allow up to 4 bytes of junk to precede status line.
451TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
452 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35453 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42454 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27455 };
[email protected]31a2bfe2010-02-09 08:03:39456 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
457 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42458 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27459 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
460 EXPECT_EQ("DATA", out.response_data);
461}
462
463// Allow up to 4 bytes of junk to precede status line.
464TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
465 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35466 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42467 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27468 };
[email protected]31a2bfe2010-02-09 08:03:39469 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
470 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42471 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27472 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
473 EXPECT_EQ("DATA", out.response_data);
474}
475
476// Beyond 4 bytes of slop and it should fail to find a status line.
477TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
478 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35479 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42480 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27481 };
[email protected]31a2bfe2010-02-09 08:03:39482 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
483 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42484 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25485 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
486 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27487}
488
489// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
490TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
491 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35492 MockRead("\n"),
493 MockRead("\n"),
494 MockRead("Q"),
495 MockRead("J"),
496 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42497 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27498 };
[email protected]31a2bfe2010-02-09 08:03:39499 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
500 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42501 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27502 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
503 EXPECT_EQ("DATA", out.response_data);
504}
505
506// Close the connection before enough bytes to have a status line.
507TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
508 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35509 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42510 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27511 };
[email protected]31a2bfe2010-02-09 08:03:39512 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
513 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42514 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27515 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
516 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52517}
518
[email protected]f9d44aa2008-09-23 23:57:17519// Simulate a 204 response, lacking a Content-Length header, sent over a
520// persistent connection. The response should still terminate since a 204
521// cannot have a response body.
522TEST_F(HttpNetworkTransactionTest, StopsReading204) {
523 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35524 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
525 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42526 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17527 };
[email protected]31a2bfe2010-02-09 08:03:39528 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
529 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42530 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17531 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
532 EXPECT_EQ("", out.response_data);
533}
534
[email protected]0877e3d2009-10-17 22:29:57535// A simple request using chunked encoding with some extra data after.
536// (Like might be seen in a pipelined response.)
537TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
538 MockRead data_reads[] = {
539 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
540 MockRead("5\r\nHello\r\n"),
541 MockRead("1\r\n"),
542 MockRead(" \r\n"),
543 MockRead("5\r\nworld\r\n"),
544 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
545 MockRead(false, OK),
546 };
[email protected]31a2bfe2010-02-09 08:03:39547 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
548 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57549 EXPECT_EQ(OK, out.rv);
550 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
551 EXPECT_EQ("Hello world", out.response_data);
552}
553
[email protected]9fe44f52010-09-23 18:36:00554// Next tests deal with http://crbug.com/56344.
555
556TEST_F(HttpNetworkTransactionTest,
557 MultipleContentLengthHeadersNoTransferEncoding) {
558 MockRead data_reads[] = {
559 MockRead("HTTP/1.1 200 OK\r\n"),
560 MockRead("Content-Length: 10\r\n"),
561 MockRead("Content-Length: 5\r\n\r\n"),
562 };
563 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
564 arraysize(data_reads));
565 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
566}
567
568TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04569 DuplicateContentLengthHeadersNoTransferEncoding) {
570 MockRead data_reads[] = {
571 MockRead("HTTP/1.1 200 OK\r\n"),
572 MockRead("Content-Length: 5\r\n"),
573 MockRead("Content-Length: 5\r\n\r\n"),
574 MockRead("Hello"),
575 };
576 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
577 arraysize(data_reads));
578 EXPECT_EQ(OK, out.rv);
579 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
580 EXPECT_EQ("Hello", out.response_data);
581}
582
583TEST_F(HttpNetworkTransactionTest,
584 ComplexContentLengthHeadersNoTransferEncoding) {
585 // More than 2 dupes.
586 {
587 MockRead data_reads[] = {
588 MockRead("HTTP/1.1 200 OK\r\n"),
589 MockRead("Content-Length: 5\r\n"),
590 MockRead("Content-Length: 5\r\n"),
591 MockRead("Content-Length: 5\r\n\r\n"),
592 MockRead("Hello"),
593 };
594 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
595 arraysize(data_reads));
596 EXPECT_EQ(OK, out.rv);
597 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
598 EXPECT_EQ("Hello", out.response_data);
599 }
600 // HTTP/1.0
601 {
602 MockRead data_reads[] = {
603 MockRead("HTTP/1.0 200 OK\r\n"),
604 MockRead("Content-Length: 5\r\n"),
605 MockRead("Content-Length: 5\r\n"),
606 MockRead("Content-Length: 5\r\n\r\n"),
607 MockRead("Hello"),
608 };
609 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
610 arraysize(data_reads));
611 EXPECT_EQ(OK, out.rv);
612 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
613 EXPECT_EQ("Hello", out.response_data);
614 }
615 // 2 dupes and one mismatched.
616 {
617 MockRead data_reads[] = {
618 MockRead("HTTP/1.1 200 OK\r\n"),
619 MockRead("Content-Length: 10\r\n"),
620 MockRead("Content-Length: 10\r\n"),
621 MockRead("Content-Length: 5\r\n\r\n"),
622 };
623 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
624 arraysize(data_reads));
625 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
626 }
627}
628
629TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00630 MultipleContentLengthHeadersTransferEncoding) {
631 MockRead data_reads[] = {
632 MockRead("HTTP/1.1 200 OK\r\n"),
633 MockRead("Content-Length: 666\r\n"),
634 MockRead("Content-Length: 1337\r\n"),
635 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
636 MockRead("5\r\nHello\r\n"),
637 MockRead("1\r\n"),
638 MockRead(" \r\n"),
639 MockRead("5\r\nworld\r\n"),
640 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
641 MockRead(false, OK),
642 };
643 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
644 arraysize(data_reads));
645 EXPECT_EQ(OK, out.rv);
646 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
647 EXPECT_EQ("Hello world", out.response_data);
648}
649
[email protected]1628fe92011-10-04 23:04:55650// Next tests deal with http://crbug.com/98895.
651
652// Checks that a single Content-Disposition header results in no error.
653TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
654 MockRead data_reads[] = {
655 MockRead("HTTP/1.1 200 OK\r\n"),
656 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
657 MockRead("Content-Length: 5\r\n\r\n"),
658 MockRead("Hello"),
659 };
660 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
661 arraysize(data_reads));
662 EXPECT_EQ(OK, out.rv);
663 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
664 EXPECT_EQ("Hello", out.response_data);
665}
666
667// Checks that two identical Content-Disposition headers result in an error.
668TEST_F(HttpNetworkTransactionTest,
669 DuplicateIdenticalContentDispositionHeaders) {
670 MockRead data_reads[] = {
671 MockRead("HTTP/1.1 200 OK\r\n"),
672 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
673 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
674 MockRead("Content-Length: 5\r\n\r\n"),
675 MockRead("Hello"),
676 };
677 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
678 arraysize(data_reads));
679 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
680}
681
682// Checks that two distinct Content-Disposition headers result in an error.
683TEST_F(HttpNetworkTransactionTest, DuplicateDistinctContentDispositionHeaders) {
684 MockRead data_reads[] = {
685 MockRead("HTTP/1.1 200 OK\r\n"),
686 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
687 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
688 MockRead("Content-Length: 5\r\n\r\n"),
689 MockRead("Hello"),
690 };
691 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
692 arraysize(data_reads));
693 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
694}
695
696// Checks the behavior of a single Location header.
697TEST_F(HttpNetworkTransactionTest, SingleLocationHeader) {
698 MockRead data_reads[] = {
699 MockRead("HTTP/1.1 302 Redirect\r\n"),
700 MockRead("Location: http://good.com/\r\n"),
701 MockRead("Content-Length: 0\r\n\r\n"),
702 MockRead(false, OK),
703 };
704
705 HttpRequestInfo request;
706 request.method = "GET";
707 request.url = GURL("http://redirect.com/");
708 request.load_flags = 0;
709
710 SessionDependencies session_deps;
711 scoped_ptr<HttpTransaction> trans(
712 new HttpNetworkTransaction(CreateSession(&session_deps)));
713
714 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
715 session_deps.socket_factory.AddSocketDataProvider(&data);
716
717 TestOldCompletionCallback callback;
718
719 int rv = trans->Start(&request, &callback, BoundNetLog());
720 EXPECT_EQ(ERR_IO_PENDING, rv);
721
722 EXPECT_EQ(OK, callback.WaitForResult());
723
724 const HttpResponseInfo* response = trans->GetResponseInfo();
725 ASSERT_TRUE(response != NULL && response->headers != NULL);
726 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
727 std::string url;
728 EXPECT_TRUE(response->headers->IsRedirect(&url));
729 EXPECT_EQ("http://good.com/", url);
730}
731
732// Checks that two identical Location headers result in an error.
733TEST_F(HttpNetworkTransactionTest, DuplicateIdenticalLocationHeaders) {
734 MockRead data_reads[] = {
735 MockRead("HTTP/1.1 302 Redirect\r\n"),
736 MockRead("Location: http://good.com/\r\n"),
737 MockRead("Location: http://good.com/\r\n"),
738 MockRead("Content-Length: 0\r\n\r\n"),
739 MockRead(false, OK),
740 };
741 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
742 arraysize(data_reads));
743 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
744}
745
746// Checks that two distinct Location headers result in an error.
747TEST_F(HttpNetworkTransactionTest, DuplicateDistinctLocationHeaders) {
748 MockRead data_reads[] = {
749 MockRead("HTTP/1.1 302 Redirect\r\n"),
750 MockRead("Location: http://good.com/\r\n"),
751 MockRead("Location: http://evil.com/\r\n"),
752 MockRead("Content-Length: 0\r\n\r\n"),
753 MockRead(false, OK),
754 };
755 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
756 arraysize(data_reads));
757 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
758}
759
[email protected]ef0faf2e72009-03-05 23:27:23760// Do a request using the HEAD method. Verify that we don't try to read the
761// message body (since HEAD has none).
762TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42763 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23764 request.method = "HEAD";
765 request.url = GURL("http://www.google.com/");
766 request.load_flags = 0;
767
[email protected]cb9bf6ca2011-01-28 13:15:27768 SessionDependencies session_deps;
769 scoped_ptr<HttpTransaction> trans(
770 new HttpNetworkTransaction(CreateSession(&session_deps)));
771
[email protected]ef0faf2e72009-03-05 23:27:23772 MockWrite data_writes1[] = {
773 MockWrite("HEAD / HTTP/1.1\r\n"
774 "Host: www.google.com\r\n"
775 "Connection: keep-alive\r\n"
776 "Content-Length: 0\r\n\r\n"),
777 };
778 MockRead data_reads1[] = {
779 MockRead("HTTP/1.1 404 Not Found\r\n"),
780 MockRead("Server: Blah\r\n"),
781 MockRead("Content-Length: 1234\r\n\r\n"),
782
783 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42784 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23785 };
786
[email protected]31a2bfe2010-02-09 08:03:39787 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
788 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59789 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23790
[email protected]f1f3f0f82011-10-01 20:38:10791 TestOldCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:23792
[email protected]5a1d7ca2010-04-28 20:12:27793 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42794 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23795
796 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42797 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23798
[email protected]1c773ea12009-04-28 19:58:42799 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50800 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:23801
802 // Check that the headers got parsed.
803 EXPECT_TRUE(response->headers != NULL);
804 EXPECT_EQ(1234, response->headers->GetContentLength());
805 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
806
807 std::string server_header;
808 void* iter = NULL;
809 bool has_server_header = response->headers->EnumerateHeader(
810 &iter, "Server", &server_header);
811 EXPECT_TRUE(has_server_header);
812 EXPECT_EQ("Blah", server_header);
813
814 // Reading should give EOF right away, since there is no message body
815 // (despite non-zero content-length).
816 std::string response_data;
817 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42818 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23819 EXPECT_EQ("", response_data);
820}
821
initial.commit586acc5fe2008-07-26 22:42:52822TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59823 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27824 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52825
826 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35827 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
828 MockRead("hello"),
829 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
830 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42831 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52832 };
[email protected]31a2bfe2010-02-09 08:03:39833 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59834 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52835
[email protected]0b0bf032010-09-21 18:08:50836 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52837 "hello", "world"
838 };
839
840 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42841 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52842 request.method = "GET";
843 request.url = GURL("http://www.google.com/");
844 request.load_flags = 0;
845
[email protected]cb9bf6ca2011-01-28 13:15:27846 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
847
[email protected]f1f3f0f82011-10-01 20:38:10848 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52849
[email protected]5a1d7ca2010-04-28 20:12:27850 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42851 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52852
853 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42854 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52855
[email protected]1c773ea12009-04-28 19:58:42856 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50857 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52858
859 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25860 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52861
862 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57863 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42864 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25865 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52866 }
867}
868
869TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42870 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52871 request.method = "POST";
872 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42873 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52874 request.upload_data->AppendBytes("foo", 3);
875 request.load_flags = 0;
876
[email protected]cb9bf6ca2011-01-28 13:15:27877 SessionDependencies session_deps;
878 scoped_ptr<HttpTransaction> trans(
879 new HttpNetworkTransaction(CreateSession(&session_deps)));
880
initial.commit586acc5fe2008-07-26 22:42:52881 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35882 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
883 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
884 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42885 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52886 };
[email protected]31a2bfe2010-02-09 08:03:39887 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59888 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52889
[email protected]f1f3f0f82011-10-01 20:38:10890 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52891
[email protected]5a1d7ca2010-04-28 20:12:27892 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42893 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52894
895 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42896 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52897
[email protected]1c773ea12009-04-28 19:58:42898 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50899 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52900
901 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25902 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52903
904 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57905 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42906 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25907 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52908}
909
[email protected]3a2d3662009-03-27 03:49:14910// This test is almost the same as Ignores100 above, but the response contains
911// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57912// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14913TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42914 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14915 request.method = "GET";
916 request.url = GURL("http://www.foo.com/");
917 request.load_flags = 0;
918
[email protected]cb9bf6ca2011-01-28 13:15:27919 SessionDependencies session_deps;
920 scoped_ptr<HttpTransaction> trans(
921 new HttpNetworkTransaction(CreateSession(&session_deps)));
922
[email protected]3a2d3662009-03-27 03:49:14923 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57924 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
925 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14926 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42927 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14928 };
[email protected]31a2bfe2010-02-09 08:03:39929 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59930 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14931
[email protected]f1f3f0f82011-10-01 20:38:10932 TestOldCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:14933
[email protected]5a1d7ca2010-04-28 20:12:27934 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42935 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14936
937 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42938 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14939
[email protected]1c773ea12009-04-28 19:58:42940 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50941 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:14942
943 EXPECT_TRUE(response->headers != NULL);
944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
945
946 std::string response_data;
947 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42948 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14949 EXPECT_EQ("hello world", response_data);
950}
951
[email protected]ee9410e72010-01-07 01:42:38952TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38953 HttpRequestInfo request;
954 request.method = "POST";
955 request.url = GURL("http://www.foo.com/");
956 request.load_flags = 0;
957
[email protected]cb9bf6ca2011-01-28 13:15:27958 SessionDependencies session_deps;
959 scoped_ptr<HttpTransaction> trans(
960 new HttpNetworkTransaction(CreateSession(&session_deps)));
961
[email protected]ee9410e72010-01-07 01:42:38962 MockRead data_reads[] = {
963 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
964 MockRead(true, 0),
965 };
[email protected]31a2bfe2010-02-09 08:03:39966 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38967 session_deps.socket_factory.AddSocketDataProvider(&data);
968
[email protected]f1f3f0f82011-10-01 20:38:10969 TestOldCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:38970
[email protected]5a1d7ca2010-04-28 20:12:27971 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38972 EXPECT_EQ(ERR_IO_PENDING, rv);
973
974 rv = callback.WaitForResult();
975 EXPECT_EQ(OK, rv);
976
977 std::string response_data;
978 rv = ReadTransaction(trans.get(), &response_data);
979 EXPECT_EQ(OK, rv);
980 EXPECT_EQ("", response_data);
981}
982
983TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38984 HttpRequestInfo request;
985 request.method = "POST";
986 request.url = GURL("http://www.foo.com/");
987 request.load_flags = 0;
988
[email protected]cb9bf6ca2011-01-28 13:15:27989 SessionDependencies session_deps;
990 scoped_ptr<HttpTransaction> trans(
991 new HttpNetworkTransaction(CreateSession(&session_deps)));
992
[email protected]ee9410e72010-01-07 01:42:38993 MockRead data_reads[] = {
994 MockRead(true, 0),
995 };
[email protected]31a2bfe2010-02-09 08:03:39996 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38997 session_deps.socket_factory.AddSocketDataProvider(&data);
998
[email protected]f1f3f0f82011-10-01 20:38:10999 TestOldCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381000
[email protected]5a1d7ca2010-04-28 20:12:271001 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381002 EXPECT_EQ(ERR_IO_PENDING, rv);
1003
1004 rv = callback.WaitForResult();
1005 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1006}
1007
[email protected]3d2a59b2008-09-26 19:44:251008// read_failure specifies a read failure that should cause the network
1009// transaction to resend the request.
1010void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1011 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:421012 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521013 request.method = "GET";
1014 request.url = GURL("http://www.foo.com/");
1015 request.load_flags = 0;
1016
[email protected]cb9bf6ca2011-01-28 13:15:271017 SessionDependencies session_deps;
1018 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1019
initial.commit586acc5fe2008-07-26 22:42:521020 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351021 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1022 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:251023 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:521024 };
[email protected]31a2bfe2010-02-09 08:03:391025 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591026 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521027
1028 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351029 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1030 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:421031 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:521032 };
[email protected]31a2bfe2010-02-09 08:03:391033 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591034 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521035
1036 const char* kExpectedResponseData[] = {
1037 "hello", "world"
1038 };
1039
1040 for (int i = 0; i < 2; ++i) {
[email protected]f1f3f0f82011-10-01 20:38:101041 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521042
[email protected]5695b8c2009-09-30 21:36:431043 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:521044
[email protected]5a1d7ca2010-04-28 20:12:271045 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421046 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521047
1048 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421049 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521050
[email protected]1c773ea12009-04-28 19:58:421051 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501052 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521053
1054 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:251055 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521056
1057 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571058 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421059 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251060 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521061 }
1062}
[email protected]3d2a59b2008-09-26 19:44:251063
1064TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421065 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:251066 KeepAliveConnectionResendRequestTest(read_failure);
1067}
1068
1069TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:421070 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:251071 KeepAliveConnectionResendRequestTest(read_failure);
1072}
1073
1074TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421075 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251076 request.method = "GET";
1077 request.url = GURL("http://www.google.com/");
1078 request.load_flags = 0;
1079
[email protected]cb9bf6ca2011-01-28 13:15:271080 SessionDependencies session_deps;
1081 scoped_ptr<HttpTransaction> trans(
1082 new HttpNetworkTransaction(CreateSession(&session_deps)));
1083
[email protected]3d2a59b2008-09-26 19:44:251084 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421085 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351086 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1087 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:421088 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:251089 };
[email protected]31a2bfe2010-02-09 08:03:391090 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591091 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251092
[email protected]f1f3f0f82011-10-01 20:38:101093 TestOldCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251094
[email protected]5a1d7ca2010-04-28 20:12:271095 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421096 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251097
1098 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421099 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:251100
[email protected]1c773ea12009-04-28 19:58:421101 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:251102 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:251103}
1104
1105// What do various browsers do when the server closes a non-keepalive
1106// connection without sending any response header or body?
1107//
1108// IE7: error page
1109// Safari 3.1.2 (Windows): error page
1110// Firefox 3.0.1: blank page
1111// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421112// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1113// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:251114TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1115 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421116 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:351117 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1118 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:421119 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:251120 };
[email protected]31a2bfe2010-02-09 08:03:391121 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1122 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421123 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251124}
[email protected]038e9a32008-10-08 22:40:161125
[email protected]0b0bf032010-09-21 18:08:501126// Test that we correctly reuse a keep-alive connection after not explicitly
1127// reading the body.
1128TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131129 HttpRequestInfo request;
1130 request.method = "GET";
1131 request.url = GURL("http://www.foo.com/");
1132 request.load_flags = 0;
1133
[email protected]cb9bf6ca2011-01-28 13:15:271134 SessionDependencies session_deps;
1135 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1136
[email protected]0b0bf032010-09-21 18:08:501137 // Note that because all these reads happen in the same
1138 // StaticSocketDataProvider, it shows that the same socket is being reused for
1139 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:131140 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:501141 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1142 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:131143 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:501144 MockRead("HTTP/1.1 302 Found\r\n"
1145 "Content-Length: 0\r\n\r\n"),
1146 MockRead("HTTP/1.1 302 Found\r\n"
1147 "Content-Length: 5\r\n\r\n"
1148 "hello"),
1149 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1150 "Content-Length: 0\r\n\r\n"),
1151 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1152 "Content-Length: 5\r\n\r\n"
1153 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131154 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1155 MockRead("hello"),
1156 };
1157 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1158 session_deps.socket_factory.AddSocketDataProvider(&data1);
1159
1160 MockRead data2_reads[] = {
1161 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
1162 };
1163 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1164 session_deps.socket_factory.AddSocketDataProvider(&data2);
1165
[email protected]0b0bf032010-09-21 18:08:501166 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1167 std::string response_lines[kNumUnreadBodies];
1168
1169 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]f1f3f0f82011-10-01 20:38:101170 TestOldCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131171
1172 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1173
1174 int rv = trans->Start(&request, &callback, BoundNetLog());
1175 EXPECT_EQ(ERR_IO_PENDING, rv);
1176
1177 rv = callback.WaitForResult();
1178 EXPECT_EQ(OK, rv);
1179
1180 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501181 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131182
[email protected]0b0bf032010-09-21 18:08:501183 ASSERT_TRUE(response->headers != NULL);
1184 response_lines[i] = response->headers->GetStatusLine();
1185
1186 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131187 }
[email protected]0b0bf032010-09-21 18:08:501188
1189 const char* const kStatusLines[] = {
1190 "HTTP/1.1 204 No Content",
1191 "HTTP/1.1 205 Reset Content",
1192 "HTTP/1.1 304 Not Modified",
1193 "HTTP/1.1 302 Found",
1194 "HTTP/1.1 302 Found",
1195 "HTTP/1.1 301 Moved Permanently",
1196 "HTTP/1.1 301 Moved Permanently",
1197 };
1198
1199 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1200 forgot_to_update_kStatusLines);
1201
1202 for (int i = 0; i < kNumUnreadBodies; ++i)
1203 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1204
[email protected]f1f3f0f82011-10-01 20:38:101205 TestOldCompletionCallback callback;
[email protected]0b0bf032010-09-21 18:08:501206 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1207 int rv = trans->Start(&request, &callback, BoundNetLog());
1208 EXPECT_EQ(ERR_IO_PENDING, rv);
1209 rv = callback.WaitForResult();
1210 EXPECT_EQ(OK, rv);
1211 const HttpResponseInfo* response = trans->GetResponseInfo();
1212 ASSERT_TRUE(response != NULL);
1213 ASSERT_TRUE(response->headers != NULL);
1214 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1215 std::string response_data;
1216 rv = ReadTransaction(trans.get(), &response_data);
1217 EXPECT_EQ(OK, rv);
1218 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131219}
1220
[email protected]038e9a32008-10-08 22:40:161221// Test the request-challenge-retry sequence for basic auth.
1222// (basic auth is the easiest to mock, because it has no randomness).
1223TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421224 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161225 request.method = "GET";
1226 request.url = GURL("http://www.google.com/");
1227 request.load_flags = 0;
1228
[email protected]cb9bf6ca2011-01-28 13:15:271229 SessionDependencies session_deps;
1230 scoped_ptr<HttpTransaction> trans(
1231 new HttpNetworkTransaction(CreateSession(&session_deps)));
1232
[email protected]f9ee6b52008-11-08 06:46:231233 MockWrite data_writes1[] = {
1234 MockWrite("GET / HTTP/1.1\r\n"
1235 "Host: www.google.com\r\n"
1236 "Connection: keep-alive\r\n\r\n"),
1237 };
1238
[email protected]038e9a32008-10-08 22:40:161239 MockRead data_reads1[] = {
1240 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1241 // Give a couple authenticate options (only the middle one is actually
1242 // supported).
[email protected]22927ad2009-09-21 19:56:191243 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161244 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1245 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1246 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1247 // Large content-length -- won't matter, as connection will be reset.
1248 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421249 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161250 };
1251
1252 // After calling trans->RestartWithAuth(), this is the request we should
1253 // be issuing -- the final header line contains the credentials.
1254 MockWrite data_writes2[] = {
1255 MockWrite("GET / HTTP/1.1\r\n"
1256 "Host: www.google.com\r\n"
1257 "Connection: keep-alive\r\n"
1258 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1259 };
1260
1261 // Lastly, the server responds with the actual content.
1262 MockRead data_reads2[] = {
1263 MockRead("HTTP/1.0 200 OK\r\n"),
1264 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1265 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421266 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161267 };
1268
[email protected]31a2bfe2010-02-09 08:03:391269 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1270 data_writes1, arraysize(data_writes1));
1271 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1272 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591273 session_deps.socket_factory.AddSocketDataProvider(&data1);
1274 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161275
[email protected]f1f3f0f82011-10-01 20:38:101276 TestOldCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:161277
[email protected]5a1d7ca2010-04-28 20:12:271278 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421279 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161280
1281 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421282 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161283
[email protected]1c773ea12009-04-28 19:58:421284 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501285 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041286 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:161287
[email protected]f1f3f0f82011-10-01 20:38:101288 TestOldCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:161289
[email protected]f3cf9802011-10-28 18:44:581290 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]1c773ea12009-04-28 19:58:421291 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161292
1293 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421294 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161295
1296 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501297 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:161298 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1299 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161300}
1301
[email protected]861fcd52009-08-26 02:33:461302TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461303 HttpRequestInfo request;
1304 request.method = "GET";
1305 request.url = GURL("http://www.google.com/");
1306 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1307
[email protected]cb9bf6ca2011-01-28 13:15:271308 SessionDependencies session_deps;
1309 scoped_ptr<HttpTransaction> trans(
1310 new HttpNetworkTransaction(CreateSession(&session_deps)));
1311
[email protected]861fcd52009-08-26 02:33:461312 MockWrite data_writes[] = {
1313 MockWrite("GET / HTTP/1.1\r\n"
1314 "Host: www.google.com\r\n"
1315 "Connection: keep-alive\r\n\r\n"),
1316 };
1317
1318 MockRead data_reads[] = {
1319 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1320 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1321 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1322 // Large content-length -- won't matter, as connection will be reset.
1323 MockRead("Content-Length: 10000\r\n\r\n"),
1324 MockRead(false, ERR_FAILED),
1325 };
1326
[email protected]31a2bfe2010-02-09 08:03:391327 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1328 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591329 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f1f3f0f82011-10-01 20:38:101330 TestOldCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:461331
[email protected]5a1d7ca2010-04-28 20:12:271332 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461333 EXPECT_EQ(ERR_IO_PENDING, rv);
1334
1335 rv = callback.WaitForResult();
1336 EXPECT_EQ(0, rv);
1337
1338 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501339 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:461340 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1341}
1342
[email protected]2d2697f92009-02-18 21:00:321343// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1344// connection.
1345TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421346 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321347 request.method = "GET";
1348 request.url = GURL("http://www.google.com/");
1349 request.load_flags = 0;
1350
[email protected]cb9bf6ca2011-01-28 13:15:271351 SessionDependencies session_deps;
1352 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1353
[email protected]2d2697f92009-02-18 21:00:321354 MockWrite data_writes1[] = {
1355 MockWrite("GET / HTTP/1.1\r\n"
1356 "Host: www.google.com\r\n"
1357 "Connection: keep-alive\r\n\r\n"),
1358
1359 // After calling trans->RestartWithAuth(), this is the request we should
1360 // be issuing -- the final header line contains the credentials.
1361 MockWrite("GET / HTTP/1.1\r\n"
1362 "Host: www.google.com\r\n"
1363 "Connection: keep-alive\r\n"
1364 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1365 };
1366
1367 MockRead data_reads1[] = {
1368 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1369 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1370 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1371 MockRead("Content-Length: 14\r\n\r\n"),
1372 MockRead("Unauthorized\r\n"),
1373
1374 // Lastly, the server responds with the actual content.
1375 MockRead("HTTP/1.1 200 OK\r\n"),
1376 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501377 MockRead("Content-Length: 5\r\n\r\n"),
1378 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321379 };
1380
[email protected]2d0a4f92011-05-05 16:38:461381 // If there is a regression where we disconnect a Keep-Alive
1382 // connection during an auth roundtrip, we'll end up reading this.
1383 MockRead data_reads2[] = {
1384 MockRead(false, ERR_FAILED),
1385 };
1386
[email protected]31a2bfe2010-02-09 08:03:391387 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1388 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461389 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1390 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591391 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461392 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321393
[email protected]f1f3f0f82011-10-01 20:38:101394 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321395
[email protected]0b0bf032010-09-21 18:08:501396 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271397 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421398 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321399
1400 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421401 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321402
[email protected]1c773ea12009-04-28 19:58:421403 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501404 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041405 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321406
[email protected]f1f3f0f82011-10-01 20:38:101407 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321408
[email protected]f3cf9802011-10-28 18:44:581409 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]1c773ea12009-04-28 19:58:421410 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321411
1412 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421413 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321414
1415 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501416 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321417 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501418 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321419}
1420
1421// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1422// connection and with no response body to drain.
1423TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421424 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321425 request.method = "GET";
1426 request.url = GURL("http://www.google.com/");
1427 request.load_flags = 0;
1428
[email protected]cb9bf6ca2011-01-28 13:15:271429 SessionDependencies session_deps;
1430 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1431
[email protected]2d2697f92009-02-18 21:00:321432 MockWrite data_writes1[] = {
1433 MockWrite("GET / HTTP/1.1\r\n"
1434 "Host: www.google.com\r\n"
1435 "Connection: keep-alive\r\n\r\n"),
1436
1437 // After calling trans->RestartWithAuth(), this is the request we should
1438 // be issuing -- the final header line contains the credentials.
1439 MockWrite("GET / HTTP/1.1\r\n"
1440 "Host: www.google.com\r\n"
1441 "Connection: keep-alive\r\n"
1442 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1443 };
1444
[email protected]2d2697f92009-02-18 21:00:321445 MockRead data_reads1[] = {
1446 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1447 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311448 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321449
1450 // Lastly, the server responds with the actual content.
1451 MockRead("HTTP/1.1 200 OK\r\n"),
1452 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501453 MockRead("Content-Length: 5\r\n\r\n"),
1454 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321455 };
1456
[email protected]2d0a4f92011-05-05 16:38:461457 // An incorrect reconnect would cause this to be read.
1458 MockRead data_reads2[] = {
1459 MockRead(false, ERR_FAILED),
1460 };
1461
[email protected]31a2bfe2010-02-09 08:03:391462 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1463 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461464 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1465 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591466 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461467 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321468
[email protected]f1f3f0f82011-10-01 20:38:101469 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321470
[email protected]0b0bf032010-09-21 18:08:501471 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271472 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421473 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321474
1475 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421476 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321477
[email protected]1c773ea12009-04-28 19:58:421478 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501479 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041480 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321481
[email protected]f1f3f0f82011-10-01 20:38:101482 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321483
[email protected]f3cf9802011-10-28 18:44:581484 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]1c773ea12009-04-28 19:58:421485 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321486
1487 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421488 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321489
1490 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501491 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321492 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501493 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321494}
1495
1496// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1497// connection and with a large response body to drain.
1498TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421499 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321500 request.method = "GET";
1501 request.url = GURL("http://www.google.com/");
1502 request.load_flags = 0;
1503
[email protected]cb9bf6ca2011-01-28 13:15:271504 SessionDependencies session_deps;
1505 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1506
[email protected]2d2697f92009-02-18 21:00:321507 MockWrite data_writes1[] = {
1508 MockWrite("GET / HTTP/1.1\r\n"
1509 "Host: www.google.com\r\n"
1510 "Connection: keep-alive\r\n\r\n"),
1511
1512 // After calling trans->RestartWithAuth(), this is the request we should
1513 // be issuing -- the final header line contains the credentials.
1514 MockWrite("GET / HTTP/1.1\r\n"
1515 "Host: www.google.com\r\n"
1516 "Connection: keep-alive\r\n"
1517 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1518 };
1519
1520 // Respond with 5 kb of response body.
1521 std::string large_body_string("Unauthorized");
1522 large_body_string.append(5 * 1024, ' ');
1523 large_body_string.append("\r\n");
1524
1525 MockRead data_reads1[] = {
1526 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1527 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1528 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1529 // 5134 = 12 + 5 * 1024 + 2
1530 MockRead("Content-Length: 5134\r\n\r\n"),
1531 MockRead(true, large_body_string.data(), large_body_string.size()),
1532
1533 // Lastly, the server responds with the actual content.
1534 MockRead("HTTP/1.1 200 OK\r\n"),
1535 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501536 MockRead("Content-Length: 5\r\n\r\n"),
1537 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321538 };
1539
[email protected]2d0a4f92011-05-05 16:38:461540 // An incorrect reconnect would cause this to be read.
1541 MockRead data_reads2[] = {
1542 MockRead(false, ERR_FAILED),
1543 };
1544
[email protected]31a2bfe2010-02-09 08:03:391545 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1546 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461547 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1548 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591549 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461550 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321551
[email protected]f1f3f0f82011-10-01 20:38:101552 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321553
[email protected]0b0bf032010-09-21 18:08:501554 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271555 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421556 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321557
1558 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421559 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321560
[email protected]1c773ea12009-04-28 19:58:421561 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501562 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041563 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321564
[email protected]f1f3f0f82011-10-01 20:38:101565 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321566
[email protected]f3cf9802011-10-28 18:44:581567 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]1c773ea12009-04-28 19:58:421568 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321569
1570 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421571 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321572
1573 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501574 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321575 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501576 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321577}
1578
1579// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311580// connection, but the server gets impatient and closes the connection.
1581TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311582 HttpRequestInfo request;
1583 request.method = "GET";
1584 request.url = GURL("http://www.google.com/");
1585 request.load_flags = 0;
1586
[email protected]cb9bf6ca2011-01-28 13:15:271587 SessionDependencies session_deps;
1588 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1589
[email protected]11203f012009-11-12 23:02:311590 MockWrite data_writes1[] = {
1591 MockWrite("GET / HTTP/1.1\r\n"
1592 "Host: www.google.com\r\n"
1593 "Connection: keep-alive\r\n\r\n"),
1594 // This simulates the seemingly successful write to a closed connection
1595 // if the bug is not fixed.
1596 MockWrite("GET / HTTP/1.1\r\n"
1597 "Host: www.google.com\r\n"
1598 "Connection: keep-alive\r\n"
1599 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1600 };
1601
1602 MockRead data_reads1[] = {
1603 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1604 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1605 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1606 MockRead("Content-Length: 14\r\n\r\n"),
1607 // Tell MockTCPClientSocket to simulate the server closing the connection.
1608 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1609 MockRead("Unauthorized\r\n"),
1610 MockRead(false, OK), // The server closes the connection.
1611 };
1612
1613 // After calling trans->RestartWithAuth(), this is the request we should
1614 // be issuing -- the final header line contains the credentials.
1615 MockWrite data_writes2[] = {
1616 MockWrite("GET / HTTP/1.1\r\n"
1617 "Host: www.google.com\r\n"
1618 "Connection: keep-alive\r\n"
1619 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1620 };
1621
1622 // Lastly, the server responds with the actual content.
1623 MockRead data_reads2[] = {
1624 MockRead("HTTP/1.1 200 OK\r\n"),
1625 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501626 MockRead("Content-Length: 5\r\n\r\n"),
1627 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311628 };
1629
[email protected]31a2bfe2010-02-09 08:03:391630 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1631 data_writes1, arraysize(data_writes1));
1632 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1633 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311634 session_deps.socket_factory.AddSocketDataProvider(&data1);
1635 session_deps.socket_factory.AddSocketDataProvider(&data2);
1636
[email protected]f1f3f0f82011-10-01 20:38:101637 TestOldCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:311638
[email protected]0b0bf032010-09-21 18:08:501639 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271640 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311641 EXPECT_EQ(ERR_IO_PENDING, rv);
1642
1643 rv = callback1.WaitForResult();
1644 EXPECT_EQ(OK, rv);
1645
1646 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501647 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041648 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:311649
[email protected]f1f3f0f82011-10-01 20:38:101650 TestOldCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:311651
[email protected]f3cf9802011-10-28 18:44:581652 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]11203f012009-11-12 23:02:311653 EXPECT_EQ(ERR_IO_PENDING, rv);
1654
1655 rv = callback2.WaitForResult();
1656 EXPECT_EQ(OK, rv);
1657
1658 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501659 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:311660 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501661 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311662}
1663
[email protected]394816e92010-08-03 07:38:591664// Test the request-challenge-retry sequence for basic auth, over a connection
1665// that requires a restart when setting up an SSL tunnel.
1666TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591667 HttpRequestInfo request;
1668 request.method = "GET";
1669 request.url = GURL("https://www.google.com/");
1670 // when the no authentication data flag is set.
1671 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1672
[email protected]cb9bf6ca2011-01-28 13:15:271673 // Configure against proxy server "myproxy:70".
1674 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1675 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1676 session_deps.net_log = log.bound().net_log();
1677 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1678
[email protected]394816e92010-08-03 07:38:591679 // Since we have proxy, should try to establish tunnel.
1680 MockWrite data_writes1[] = {
1681 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1682 "Host: www.google.com\r\n"
1683 "Proxy-Connection: keep-alive\r\n\r\n"),
1684
1685 // After calling trans->RestartWithAuth(), this is the request we should
1686 // be issuing -- the final header line contains the credentials.
1687 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1688 "Host: www.google.com\r\n"
1689 "Proxy-Connection: keep-alive\r\n"
1690 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1691
1692 MockWrite("GET / HTTP/1.1\r\n"
1693 "Host: www.google.com\r\n"
1694 "Connection: keep-alive\r\n\r\n"),
1695 };
1696
1697 // The proxy responds to the connect with a 407, using a persistent
1698 // connection.
1699 MockRead data_reads1[] = {
1700 // No credentials.
1701 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1702 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1703 MockRead("Proxy-Connection: close\r\n\r\n"),
1704
1705 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1706
1707 MockRead("HTTP/1.1 200 OK\r\n"),
1708 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501709 MockRead("Content-Length: 5\r\n\r\n"),
1710 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591711 };
1712
1713 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1714 data_writes1, arraysize(data_writes1));
1715 session_deps.socket_factory.AddSocketDataProvider(&data1);
1716 SSLSocketDataProvider ssl(true, OK);
1717 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1718
[email protected]f1f3f0f82011-10-01 20:38:101719 TestOldCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:591720
[email protected]0b0bf032010-09-21 18:08:501721 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1722
[email protected]394816e92010-08-03 07:38:591723 int rv = trans->Start(&request, &callback1, log.bound());
1724 EXPECT_EQ(ERR_IO_PENDING, rv);
1725
1726 rv = callback1.WaitForResult();
1727 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401728 net::CapturingNetLog::EntryList entries;
1729 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591730 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401731 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591732 NetLog::PHASE_NONE);
1733 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401734 entries, pos,
[email protected]394816e92010-08-03 07:38:591735 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1736 NetLog::PHASE_NONE);
1737
1738 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501739 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041740 ASSERT_FALSE(response->headers == NULL);
[email protected]394816e92010-08-03 07:38:591741 EXPECT_EQ(407, response->headers->response_code());
1742 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041743 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:591744
[email protected]f1f3f0f82011-10-01 20:38:101745 TestOldCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:591746
[email protected]f3cf9802011-10-28 18:44:581747 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]394816e92010-08-03 07:38:591748 EXPECT_EQ(ERR_IO_PENDING, rv);
1749
1750 rv = callback2.WaitForResult();
1751 EXPECT_EQ(OK, rv);
1752
1753 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501754 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:591755
1756 EXPECT_TRUE(response->headers->IsKeepAlive());
1757 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501758 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591759 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1760
1761 // The password prompt info should not be set.
1762 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501763
1764 trans.reset();
[email protected]102e27c2011-02-23 01:01:311765 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591766}
1767
[email protected]11203f012009-11-12 23:02:311768// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321769// proxy connection, when setting up an SSL tunnel.
1770TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271771 HttpRequestInfo request;
1772 request.method = "GET";
1773 request.url = GURL("https://www.google.com/");
1774 // Ensure that proxy authentication is attempted even
1775 // when the no authentication data flag is set.
1776 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1777
[email protected]2d2697f92009-02-18 21:00:321778 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001779 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541780 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1781 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591782 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321783
[email protected]5695b8c2009-09-30 21:36:431784 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321785
[email protected]2d2697f92009-02-18 21:00:321786 // Since we have proxy, should try to establish tunnel.
1787 MockWrite data_writes1[] = {
1788 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451789 "Host: www.google.com\r\n"
1790 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321791
1792 // After calling trans->RestartWithAuth(), this is the request we should
1793 // be issuing -- the final header line contains the credentials.
1794 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1795 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451796 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321797 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1798 };
1799
1800 // The proxy responds to the connect with a 407, using a persistent
1801 // connection.
1802 MockRead data_reads1[] = {
1803 // No credentials.
1804 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1805 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1806 MockRead("Content-Length: 10\r\n\r\n"),
1807 MockRead("0123456789"),
1808
1809 // Wrong credentials (wrong password).
1810 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1811 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1812 MockRead("Content-Length: 10\r\n\r\n"),
1813 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421814 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321815 };
1816
[email protected]31a2bfe2010-02-09 08:03:391817 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1818 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591819 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321820
[email protected]f1f3f0f82011-10-01 20:38:101821 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321822
[email protected]dbb83db2010-05-11 18:13:391823 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421824 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321825
1826 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421827 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401828 net::CapturingNetLog::EntryList entries;
1829 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391830 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401831 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391832 NetLog::PHASE_NONE);
1833 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401834 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391835 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1836 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321837
[email protected]1c773ea12009-04-28 19:58:421838 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501839 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041840 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321841 EXPECT_TRUE(response->headers->IsKeepAlive());
1842 EXPECT_EQ(407, response->headers->response_code());
1843 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421844 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041845 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321846
[email protected]f1f3f0f82011-10-01 20:38:101847 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321848
1849 // Wrong password (should be "bar").
[email protected]f3cf9802011-10-28 18:44:581850 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBaz), &callback2);
[email protected]1c773ea12009-04-28 19:58:421851 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321852
1853 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421854 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321855
1856 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501857 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041858 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321859 EXPECT_TRUE(response->headers->IsKeepAlive());
1860 EXPECT_EQ(407, response->headers->response_code());
1861 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421862 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041863 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]e772db3f2010-07-12 18:11:131864
[email protected]e60e47a2010-07-14 03:37:181865 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1866 // out of scope.
[email protected]102e27c2011-02-23 01:01:311867 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321868}
1869
[email protected]a8e9b162009-03-12 00:06:441870// Test that we don't read the response body when we fail to establish a tunnel,
1871// even if the user cancels the proxy's auth attempt.
1872TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271873 HttpRequestInfo request;
1874 request.method = "GET";
1875 request.url = GURL("https://www.google.com/");
1876 request.load_flags = 0;
1877
[email protected]a8e9b162009-03-12 00:06:441878 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001879 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441880
[email protected]e44de5d2009-06-05 20:12:451881 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441882
[email protected]5695b8c2009-09-30 21:36:431883 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441884
[email protected]a8e9b162009-03-12 00:06:441885 // Since we have proxy, should try to establish tunnel.
1886 MockWrite data_writes[] = {
1887 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451888 "Host: www.google.com\r\n"
1889 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441890 };
1891
1892 // The proxy responds to the connect with a 407.
1893 MockRead data_reads[] = {
1894 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1895 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1896 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421897 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441898 };
1899
[email protected]31a2bfe2010-02-09 08:03:391900 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1901 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591902 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441903
[email protected]f1f3f0f82011-10-01 20:38:101904 TestOldCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:441905
[email protected]5a1d7ca2010-04-28 20:12:271906 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421907 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441908
1909 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421910 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441911
[email protected]1c773ea12009-04-28 19:58:421912 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501913 ASSERT_TRUE(response != NULL);
[email protected]a8e9b162009-03-12 00:06:441914
1915 EXPECT_TRUE(response->headers->IsKeepAlive());
1916 EXPECT_EQ(407, response->headers->response_code());
1917 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421918 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441919
1920 std::string response_data;
1921 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421922 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181923
1924 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311925 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441926}
1927
[email protected]8fdbcd22010-05-05 02:54:521928// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1929// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1930TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521931 HttpRequestInfo request;
1932 request.method = "GET";
1933 request.url = GURL("http://www.google.com/");
1934 request.load_flags = 0;
1935
[email protected]cb9bf6ca2011-01-28 13:15:271936 // We are using a DIRECT connection (i.e. no proxy) for this session.
1937 SessionDependencies session_deps;
1938 scoped_ptr<HttpTransaction> trans(
1939 new HttpNetworkTransaction(CreateSession(&session_deps)));
1940
[email protected]8fdbcd22010-05-05 02:54:521941 MockWrite data_writes1[] = {
1942 MockWrite("GET / HTTP/1.1\r\n"
1943 "Host: www.google.com\r\n"
1944 "Connection: keep-alive\r\n\r\n"),
1945 };
1946
1947 MockRead data_reads1[] = {
1948 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1949 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1950 // Large content-length -- won't matter, as connection will be reset.
1951 MockRead("Content-Length: 10000\r\n\r\n"),
1952 MockRead(false, ERR_FAILED),
1953 };
1954
1955 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1956 data_writes1, arraysize(data_writes1));
1957 session_deps.socket_factory.AddSocketDataProvider(&data1);
1958
[email protected]f1f3f0f82011-10-01 20:38:101959 TestOldCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:521960
1961 int rv = trans->Start(&request, &callback, BoundNetLog());
1962 EXPECT_EQ(ERR_IO_PENDING, rv);
1963
1964 rv = callback.WaitForResult();
1965 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1966}
1967
[email protected]7a67a8152010-11-05 18:31:101968// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1969// through a non-authenticating proxy. The request should fail with
1970// ERR_UNEXPECTED_PROXY_AUTH.
1971// Note that it is impossible to detect if an HTTP server returns a 407 through
1972// a non-authenticating proxy - there is nothing to indicate whether the
1973// response came from the proxy or the server, so it is treated as if the proxy
1974// issued the challenge.
1975TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271976 HttpRequestInfo request;
1977 request.method = "GET";
1978 request.url = GURL("https://www.google.com/");
1979
[email protected]7a67a8152010-11-05 18:31:101980 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1981 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1982 session_deps.net_log = log.bound().net_log();
1983 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1984
[email protected]7a67a8152010-11-05 18:31:101985 // Since we have proxy, should try to establish tunnel.
1986 MockWrite data_writes1[] = {
1987 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1988 "Host: www.google.com\r\n"
1989 "Proxy-Connection: keep-alive\r\n\r\n"),
1990
1991 MockWrite("GET / HTTP/1.1\r\n"
1992 "Host: www.google.com\r\n"
1993 "Connection: keep-alive\r\n\r\n"),
1994 };
1995
1996 MockRead data_reads1[] = {
1997 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1998
1999 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2000 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2001 MockRead("\r\n"),
2002 MockRead(false, OK),
2003 };
2004
2005 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2006 data_writes1, arraysize(data_writes1));
2007 session_deps.socket_factory.AddSocketDataProvider(&data1);
2008 SSLSocketDataProvider ssl(true, OK);
2009 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2010
[email protected]f1f3f0f82011-10-01 20:38:102011 TestOldCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:102012
2013 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2014
2015 int rv = trans->Start(&request, &callback1, log.bound());
2016 EXPECT_EQ(ERR_IO_PENDING, rv);
2017
2018 rv = callback1.WaitForResult();
2019 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:402020 net::CapturingNetLog::EntryList entries;
2021 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:102022 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402023 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:102024 NetLog::PHASE_NONE);
2025 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402026 entries, pos,
[email protected]7a67a8152010-11-05 18:31:102027 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2028 NetLog::PHASE_NONE);
2029}
[email protected]2df19bb2010-08-25 20:13:462030
2031// Test a simple get through an HTTPS Proxy.
2032TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272033 HttpRequestInfo request;
2034 request.method = "GET";
2035 request.url = GURL("http://www.google.com/");
2036
[email protected]2df19bb2010-08-25 20:13:462037 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112038 SessionDependencies session_deps(ProxyService::CreateFixed(
2039 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462040 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2041 session_deps.net_log = log.bound().net_log();
2042 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2043
[email protected]2df19bb2010-08-25 20:13:462044 // Since we have proxy, should use full url
2045 MockWrite data_writes1[] = {
2046 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2047 "Host: www.google.com\r\n"
2048 "Proxy-Connection: keep-alive\r\n\r\n"),
2049 };
2050
2051 MockRead data_reads1[] = {
2052 MockRead("HTTP/1.1 200 OK\r\n"),
2053 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2054 MockRead("Content-Length: 100\r\n\r\n"),
2055 MockRead(false, OK),
2056 };
2057
2058 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2059 data_writes1, arraysize(data_writes1));
2060 session_deps.socket_factory.AddSocketDataProvider(&data1);
2061 SSLSocketDataProvider ssl(true, OK);
2062 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2063
[email protected]f1f3f0f82011-10-01 20:38:102064 TestOldCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462065
[email protected]0b0bf032010-09-21 18:08:502066 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2067
[email protected]2df19bb2010-08-25 20:13:462068 int rv = trans->Start(&request, &callback1, log.bound());
2069 EXPECT_EQ(ERR_IO_PENDING, rv);
2070
2071 rv = callback1.WaitForResult();
2072 EXPECT_EQ(OK, rv);
2073
2074 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502075 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462076
2077 EXPECT_TRUE(response->headers->IsKeepAlive());
2078 EXPECT_EQ(200, response->headers->response_code());
2079 EXPECT_EQ(100, response->headers->GetContentLength());
2080 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2081
2082 // The password prompt info should not be set.
2083 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2084}
2085
[email protected]7642b5ae2010-09-01 20:55:172086// Test a SPDY get through an HTTPS Proxy.
2087TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272088 HttpRequestInfo request;
2089 request.method = "GET";
2090 request.url = GURL("http://www.google.com/");
2091 request.load_flags = 0;
2092
[email protected]7642b5ae2010-09-01 20:55:172093 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112094 SessionDependencies session_deps(ProxyService::CreateFixed(
2095 "https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:172096 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2097 session_deps.net_log = log.bound().net_log();
2098 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2099
[email protected]7642b5ae2010-09-01 20:55:172100 // fetch http://www.google.com/ via SPDY
2101 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
2102 false));
2103 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2104
2105 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2106 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2107 MockRead spdy_reads[] = {
2108 CreateMockRead(*resp),
2109 CreateMockRead(*data),
2110 MockRead(true, 0, 0),
2111 };
2112
2113 scoped_refptr<DelayedSocketData> spdy_data(
2114 new DelayedSocketData(
2115 1, // wait for one write to finish before reading.
2116 spdy_reads, arraysize(spdy_reads),
2117 spdy_writes, arraysize(spdy_writes)));
2118 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2119
2120 SSLSocketDataProvider ssl(true, OK);
2121 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2122 ssl.next_proto = "spdy/2";
2123 ssl.was_npn_negotiated = true;
2124 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2125
[email protected]f1f3f0f82011-10-01 20:38:102126 TestOldCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:172127
[email protected]0b0bf032010-09-21 18:08:502128 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2129
[email protected]7642b5ae2010-09-01 20:55:172130 int rv = trans->Start(&request, &callback1, log.bound());
2131 EXPECT_EQ(ERR_IO_PENDING, rv);
2132
2133 rv = callback1.WaitForResult();
2134 EXPECT_EQ(OK, rv);
2135
2136 const HttpResponseInfo* response = trans->GetResponseInfo();
2137 ASSERT_TRUE(response != NULL);
2138 ASSERT_TRUE(response->headers != NULL);
2139 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2140
2141 std::string response_data;
2142 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2143 EXPECT_EQ(net::kUploadData, response_data);
2144}
2145
[email protected]dc7bd1c52010-11-12 00:01:132146// Test a SPDY get through an HTTPS Proxy.
2147TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272148 HttpRequestInfo request;
2149 request.method = "GET";
2150 request.url = GURL("http://www.google.com/");
2151 request.load_flags = 0;
2152
[email protected]79cb5c12011-09-12 13:12:042153 // Configure against https proxy server "myproxy:70".
[email protected]dc7bd1c52010-11-12 00:01:132154 SessionDependencies session_deps(
[email protected]79cb5c12011-09-12 13:12:042155 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]dc7bd1c52010-11-12 00:01:132156 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2157 session_deps.net_log = log.bound().net_log();
2158 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2159
[email protected]dc7bd1c52010-11-12 00:01:132160 // The first request will be a bare GET, the second request will be a
2161 // GET with a Proxy-Authorization header.
2162 scoped_ptr<spdy::SpdyFrame> req_get(
2163 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2164 const char* const kExtraAuthorizationHeaders[] = {
2165 "proxy-authorization",
2166 "Basic Zm9vOmJhcg==",
2167 };
2168 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2169 ConstructSpdyGet(
2170 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2171 false, 3, LOWEST, false));
2172 MockWrite spdy_writes[] = {
2173 CreateMockWrite(*req_get, 1),
2174 CreateMockWrite(*req_get_authorization, 4),
2175 };
2176
2177 // The first response is a 407 proxy authentication challenge, and the second
2178 // response will be a 200 response since the second request includes a valid
2179 // Authorization header.
2180 const char* const kExtraAuthenticationHeaders[] = {
2181 "Proxy-Authenticate",
2182 "Basic realm=\"MyRealm1\""
2183 };
2184 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2185 ConstructSpdySynReplyError(
2186 "407 Proxy Authentication Required",
2187 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2188 1));
2189 scoped_ptr<spdy::SpdyFrame> body_authentication(
2190 ConstructSpdyBodyFrame(1, true));
2191 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2192 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2193 MockRead spdy_reads[] = {
2194 CreateMockRead(*resp_authentication, 2),
2195 CreateMockRead(*body_authentication, 3),
2196 CreateMockRead(*resp_data, 5),
2197 CreateMockRead(*body_data, 6),
2198 MockRead(true, 0, 7),
2199 };
2200
2201 scoped_refptr<OrderedSocketData> data(
2202 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2203 spdy_writes, arraysize(spdy_writes)));
2204 session_deps.socket_factory.AddSocketDataProvider(data);
2205
2206 SSLSocketDataProvider ssl(true, OK);
2207 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2208 ssl.next_proto = "spdy/2";
2209 ssl.was_npn_negotiated = true;
2210 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2211
[email protected]f1f3f0f82011-10-01 20:38:102212 TestOldCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:132213
2214 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2215
2216 int rv = trans->Start(&request, &callback1, log.bound());
2217 EXPECT_EQ(ERR_IO_PENDING, rv);
2218
2219 rv = callback1.WaitForResult();
2220 EXPECT_EQ(OK, rv);
2221
2222 const HttpResponseInfo* const response = trans->GetResponseInfo();
2223
2224 ASSERT_TRUE(response != NULL);
2225 ASSERT_TRUE(response->headers != NULL);
2226 EXPECT_EQ(407, response->headers->response_code());
2227 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:042228 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:132229
[email protected]f1f3f0f82011-10-01 20:38:102230 TestOldCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:132231
[email protected]f3cf9802011-10-28 18:44:582232 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]dc7bd1c52010-11-12 00:01:132233 EXPECT_EQ(ERR_IO_PENDING, rv);
2234
2235 rv = callback2.WaitForResult();
2236 EXPECT_EQ(OK, rv);
2237
2238 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2239
2240 ASSERT_TRUE(response_restart != NULL);
2241 ASSERT_TRUE(response_restart->headers != NULL);
2242 EXPECT_EQ(200, response_restart->headers->response_code());
2243 // The password prompt info should not be set.
2244 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2245}
2246
[email protected]d9da5fe2010-10-13 22:37:162247// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2248TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272249 HttpRequestInfo request;
2250 request.method = "GET";
2251 request.url = GURL("https://www.google.com/");
2252 request.load_flags = 0;
2253
[email protected]d9da5fe2010-10-13 22:37:162254 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112255 SessionDependencies session_deps(ProxyService::CreateFixed(
2256 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162257 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2258 session_deps.net_log = log.bound().net_log();
2259 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2260
2261 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2262
[email protected]d9da5fe2010-10-13 22:37:162263 // CONNECT to www.google.com:443 via SPDY
2264 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2265 // fetch https://www.google.com/ via HTTP
2266
2267 const char get[] = "GET / HTTP/1.1\r\n"
2268 "Host: www.google.com\r\n"
2269 "Connection: keep-alive\r\n\r\n";
2270 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2271 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2272 MockWrite spdy_writes[] = {
2273 CreateMockWrite(*connect, 1),
2274 CreateMockWrite(*wrapped_get, 3)
2275 };
2276
2277 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2278 const char resp[] = "HTTP/1.1 200 OK\r\n"
2279 "Content-Length: 10\r\n\r\n";
2280
2281 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2282 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2283 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2284 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2285 MockRead spdy_reads[] = {
2286 CreateMockRead(*conn_resp, 2, true),
2287 CreateMockRead(*wrapped_get_resp, 4, true),
2288 CreateMockRead(*wrapped_body, 5, true),
2289 CreateMockRead(*wrapped_body, 6, true),
2290 MockRead(true, 0, 7),
2291 };
2292
2293 scoped_refptr<OrderedSocketData> spdy_data(
2294 new OrderedSocketData(
2295 spdy_reads, arraysize(spdy_reads),
2296 spdy_writes, arraysize(spdy_writes)));
2297 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2298
2299 SSLSocketDataProvider ssl(true, OK);
2300 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2301 ssl.next_proto = "spdy/2";
2302 ssl.was_npn_negotiated = true;
2303 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2304 SSLSocketDataProvider ssl2(true, OK);
2305 ssl2.was_npn_negotiated = false;
2306 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2307
[email protected]f1f3f0f82011-10-01 20:38:102308 TestOldCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162309
2310 int rv = trans->Start(&request, &callback1, log.bound());
2311 EXPECT_EQ(ERR_IO_PENDING, rv);
2312
2313 rv = callback1.WaitForResult();
2314 EXPECT_EQ(OK, rv);
2315
2316 const HttpResponseInfo* response = trans->GetResponseInfo();
2317 ASSERT_TRUE(response != NULL);
2318 ASSERT_TRUE(response->headers != NULL);
2319 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2320
2321 std::string response_data;
2322 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2323 EXPECT_EQ("1234567890", response_data);
2324}
2325
2326// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2327TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272328 HttpRequestInfo request;
2329 request.method = "GET";
2330 request.url = GURL("https://www.google.com/");
2331 request.load_flags = 0;
2332
[email protected]d9da5fe2010-10-13 22:37:162333 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112334 SessionDependencies session_deps(ProxyService::CreateFixed(
2335 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162336 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2337 session_deps.net_log = log.bound().net_log();
2338 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2339
2340 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2341
[email protected]d9da5fe2010-10-13 22:37:162342 // CONNECT to www.google.com:443 via SPDY
2343 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2344 // fetch https://www.google.com/ via SPDY
2345 const char* const kMyUrl = "https://www.google.com/";
2346 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2347 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2348 MockWrite spdy_writes[] = {
2349 CreateMockWrite(*connect, 1),
2350 CreateMockWrite(*wrapped_get, 3)
2351 };
2352
2353 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2354 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2355 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2356 ConstructWrappedSpdyFrame(get_resp, 1));
2357 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2358 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2359 MockRead spdy_reads[] = {
2360 CreateMockRead(*conn_resp, 2, true),
2361 CreateMockRead(*wrapped_get_resp, 4, true),
2362 CreateMockRead(*wrapped_body, 5, true),
2363 MockRead(true, 0, 1),
2364 };
2365
2366 scoped_refptr<OrderedSocketData> spdy_data(
2367 new OrderedSocketData(
2368 spdy_reads, arraysize(spdy_reads),
2369 spdy_writes, arraysize(spdy_writes)));
2370 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2371
2372 SSLSocketDataProvider ssl(true, OK);
2373 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2374 ssl.next_proto = "spdy/2";
2375 ssl.was_npn_negotiated = true;
2376 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2377 SSLSocketDataProvider ssl2(true, OK);
2378 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2379 ssl2.next_proto = "spdy/2";
2380 ssl2.was_npn_negotiated = true;
2381 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2382
[email protected]f1f3f0f82011-10-01 20:38:102383 TestOldCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162384
2385 int rv = trans->Start(&request, &callback1, log.bound());
2386 EXPECT_EQ(ERR_IO_PENDING, rv);
2387
2388 rv = callback1.WaitForResult();
2389 EXPECT_EQ(OK, rv);
2390
2391 const HttpResponseInfo* response = trans->GetResponseInfo();
2392 ASSERT_TRUE(response != NULL);
2393 ASSERT_TRUE(response->headers != NULL);
2394 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2395
2396 std::string response_data;
2397 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2398 EXPECT_EQ(net::kUploadData, response_data);
2399}
2400
2401// Test a SPDY CONNECT failure through an HTTPS Proxy.
2402TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272403 HttpRequestInfo request;
2404 request.method = "GET";
2405 request.url = GURL("https://www.google.com/");
2406 request.load_flags = 0;
2407
[email protected]d9da5fe2010-10-13 22:37:162408 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112409 SessionDependencies session_deps(ProxyService::CreateFixed(
2410 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162411 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2412 session_deps.net_log = log.bound().net_log();
2413 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2414
2415 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2416
[email protected]d9da5fe2010-10-13 22:37:162417 // CONNECT to www.google.com:443 via SPDY
2418 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2419 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2420
2421 MockWrite spdy_writes[] = {
2422 CreateMockWrite(*connect, 1),
2423 CreateMockWrite(*get, 3),
2424 };
2425
2426 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2427 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2428 MockRead spdy_reads[] = {
2429 CreateMockRead(*resp, 2, true),
2430 MockRead(true, 0, 4),
2431 };
2432
2433 scoped_refptr<OrderedSocketData> spdy_data(
2434 new OrderedSocketData(
2435 spdy_reads, arraysize(spdy_reads),
2436 spdy_writes, arraysize(spdy_writes)));
2437 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2438
2439 SSLSocketDataProvider ssl(true, OK);
2440 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2441 ssl.next_proto = "spdy/2";
2442 ssl.was_npn_negotiated = true;
2443 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2444 SSLSocketDataProvider ssl2(true, OK);
2445 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2446 ssl2.next_proto = "spdy/2";
2447 ssl2.was_npn_negotiated = true;
2448 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2449
[email protected]f1f3f0f82011-10-01 20:38:102450 TestOldCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162451
2452 int rv = trans->Start(&request, &callback1, log.bound());
2453 EXPECT_EQ(ERR_IO_PENDING, rv);
2454
2455 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292456 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162457
2458 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502459 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:292460 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162461}
2462
[email protected]2df19bb2010-08-25 20:13:462463// Test the challenge-response-retry sequence through an HTTPS Proxy
2464TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462465 HttpRequestInfo request;
2466 request.method = "GET";
2467 request.url = GURL("http://www.google.com/");
2468 // when the no authentication data flag is set.
2469 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2470
[email protected]79cb5c12011-09-12 13:12:042471 // Configure against https proxy server "myproxy:70".
2472 SessionDependencies session_deps(
2473 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]cb9bf6ca2011-01-28 13:15:272474 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2475 session_deps.net_log = log.bound().net_log();
2476 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2477
[email protected]2df19bb2010-08-25 20:13:462478 // Since we have proxy, should use full url
2479 MockWrite data_writes1[] = {
2480 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2481 "Host: www.google.com\r\n"
2482 "Proxy-Connection: keep-alive\r\n\r\n"),
2483
2484 // After calling trans->RestartWithAuth(), this is the request we should
2485 // be issuing -- the final header line contains the credentials.
2486 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2487 "Host: www.google.com\r\n"
2488 "Proxy-Connection: keep-alive\r\n"
2489 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2490 };
2491
2492 // The proxy responds to the GET with a 407, using a persistent
2493 // connection.
2494 MockRead data_reads1[] = {
2495 // No credentials.
2496 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2497 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2498 MockRead("Proxy-Connection: keep-alive\r\n"),
2499 MockRead("Content-Length: 0\r\n\r\n"),
2500
2501 MockRead("HTTP/1.1 200 OK\r\n"),
2502 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2503 MockRead("Content-Length: 100\r\n\r\n"),
2504 MockRead(false, OK),
2505 };
2506
2507 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2508 data_writes1, arraysize(data_writes1));
2509 session_deps.socket_factory.AddSocketDataProvider(&data1);
2510 SSLSocketDataProvider ssl(true, OK);
2511 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2512
[email protected]f1f3f0f82011-10-01 20:38:102513 TestOldCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462514
[email protected]0b0bf032010-09-21 18:08:502515 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2516
[email protected]2df19bb2010-08-25 20:13:462517 int rv = trans->Start(&request, &callback1, log.bound());
2518 EXPECT_EQ(ERR_IO_PENDING, rv);
2519
2520 rv = callback1.WaitForResult();
2521 EXPECT_EQ(OK, rv);
2522
2523 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502524 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042525 ASSERT_FALSE(response->headers == NULL);
[email protected]2df19bb2010-08-25 20:13:462526 EXPECT_EQ(407, response->headers->response_code());
2527 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042528 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:462529
[email protected]f1f3f0f82011-10-01 20:38:102530 TestOldCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:462531
[email protected]f3cf9802011-10-28 18:44:582532 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]2df19bb2010-08-25 20:13:462533 EXPECT_EQ(ERR_IO_PENDING, rv);
2534
2535 rv = callback2.WaitForResult();
2536 EXPECT_EQ(OK, rv);
2537
2538 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502539 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462540
2541 EXPECT_TRUE(response->headers->IsKeepAlive());
2542 EXPECT_EQ(200, response->headers->response_code());
2543 EXPECT_EQ(100, response->headers->GetContentLength());
2544 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2545
2546 // The password prompt info should not be set.
2547 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2548}
2549
[email protected]ff007e162009-05-23 09:13:152550void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082551 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422552 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082553 request.method = "GET";
2554 request.url = GURL("https://www.google.com/");
2555 request.load_flags = 0;
2556
[email protected]cb9bf6ca2011-01-28 13:15:272557 // Configure against proxy server "myproxy:70".
2558 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2559
2560 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2561
[email protected]c744cf22009-02-27 07:28:082562 // Since we have proxy, should try to establish tunnel.
2563 MockWrite data_writes[] = {
2564 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452565 "Host: www.google.com\r\n"
2566 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082567 };
2568
2569 MockRead data_reads[] = {
2570 status,
2571 MockRead("Content-Length: 10\r\n\r\n"),
2572 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422573 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082574 };
2575
[email protected]31a2bfe2010-02-09 08:03:392576 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2577 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592578 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082579
[email protected]f1f3f0f82011-10-01 20:38:102580 TestOldCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:082581
[email protected]0b0bf032010-09-21 18:08:502582 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2583
[email protected]5a1d7ca2010-04-28 20:12:272584 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422585 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082586
2587 rv = callback.WaitForResult();
2588 EXPECT_EQ(expected_status, rv);
2589}
2590
[email protected]ff007e162009-05-23 09:13:152591void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082592 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422593 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082594}
2595
2596TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2597 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2598}
2599
2600TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2601 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2602}
2603
2604TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2605 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2606}
2607
2608TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2609 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2610}
2611
2612TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2613 ConnectStatusHelper(
2614 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2615}
2616
2617TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2618 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2619}
2620
2621TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2622 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2623}
2624
2625TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2626 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2627}
2628
2629TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2630 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2631}
2632
2633TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2634 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2635}
2636
2637TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2638 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2639}
2640
2641TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2642 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2643}
2644
2645TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2646 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2647}
2648
2649TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2650 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2651}
2652
2653TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2654 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2655}
2656
2657TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2658 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2659}
2660
2661TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2662 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2663}
2664
2665TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2666 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2667}
2668
2669TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2670 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2671}
2672
2673TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2674 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2675}
2676
2677TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2678 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2679}
2680
2681TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2682 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2683}
2684
2685TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2686 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2687}
2688
2689TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2690 ConnectStatusHelperWithExpectedStatus(
2691 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542692 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082693}
2694
2695TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2696 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2697}
2698
2699TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2700 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2701}
2702
2703TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2704 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2705}
2706
2707TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2708 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2709}
2710
2711TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2712 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2713}
2714
2715TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2716 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2717}
2718
2719TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2720 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2721}
2722
2723TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2724 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2725}
2726
2727TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2728 ConnectStatusHelper(
2729 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2730}
2731
2732TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2733 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2734}
2735
2736TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2737 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2738}
2739
2740TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2741 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2742}
2743
2744TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2745 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2746}
2747
2748TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2749 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2750}
2751
2752TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2753 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2754}
2755
2756TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2757 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2758}
2759
[email protected]038e9a32008-10-08 22:40:162760// Test the flow when both the proxy server AND origin server require
2761// authentication. Again, this uses basic auth for both since that is
2762// the simplest to mock.
2763TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272764 HttpRequestInfo request;
2765 request.method = "GET";
2766 request.url = GURL("http://www.google.com/");
2767 request.load_flags = 0;
2768
[email protected]81cdfcd2010-10-16 00:49:002769 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012770
[email protected]038e9a32008-10-08 22:40:162771 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422772 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432773 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162774
[email protected]f9ee6b52008-11-08 06:46:232775 MockWrite data_writes1[] = {
2776 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2777 "Host: www.google.com\r\n"
2778 "Proxy-Connection: keep-alive\r\n\r\n"),
2779 };
2780
[email protected]038e9a32008-10-08 22:40:162781 MockRead data_reads1[] = {
2782 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2783 // Give a couple authenticate options (only the middle one is actually
2784 // supported).
[email protected]22927ad2009-09-21 19:56:192785 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162786 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2787 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2788 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2789 // Large content-length -- won't matter, as connection will be reset.
2790 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422791 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162792 };
2793
2794 // After calling trans->RestartWithAuth() the first time, this is the
2795 // request we should be issuing -- the final header line contains the
2796 // proxy's credentials.
2797 MockWrite data_writes2[] = {
2798 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2799 "Host: www.google.com\r\n"
2800 "Proxy-Connection: keep-alive\r\n"
2801 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2802 };
2803
2804 // Now the proxy server lets the request pass through to origin server.
2805 // The origin server responds with a 401.
2806 MockRead data_reads2[] = {
2807 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2808 // Note: We are using the same realm-name as the proxy server. This is
2809 // completely valid, as realms are unique across hosts.
2810 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2811 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2812 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422813 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162814 };
2815
2816 // After calling trans->RestartWithAuth() the second time, we should send
2817 // the credentials for both the proxy and origin server.
2818 MockWrite data_writes3[] = {
2819 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2820 "Host: www.google.com\r\n"
2821 "Proxy-Connection: keep-alive\r\n"
2822 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2823 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2824 };
2825
2826 // Lastly we get the desired content.
2827 MockRead data_reads3[] = {
2828 MockRead("HTTP/1.0 200 OK\r\n"),
2829 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2830 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422831 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162832 };
2833
[email protected]31a2bfe2010-02-09 08:03:392834 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2835 data_writes1, arraysize(data_writes1));
2836 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2837 data_writes2, arraysize(data_writes2));
2838 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2839 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592840 session_deps.socket_factory.AddSocketDataProvider(&data1);
2841 session_deps.socket_factory.AddSocketDataProvider(&data2);
2842 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162843
[email protected]f1f3f0f82011-10-01 20:38:102844 TestOldCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162845
[email protected]5a1d7ca2010-04-28 20:12:272846 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422847 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162848
2849 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422850 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162851
[email protected]1c773ea12009-04-28 19:58:422852 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502853 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042854 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162855
[email protected]f1f3f0f82011-10-01 20:38:102856 TestOldCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162857
[email protected]f3cf9802011-10-28 18:44:582858 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]1c773ea12009-04-28 19:58:422859 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162860
2861 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422862 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162863
2864 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502865 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042866 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162867
[email protected]f1f3f0f82011-10-01 20:38:102868 TestOldCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:162869
[email protected]f3cf9802011-10-28 18:44:582870 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2), &callback3);
[email protected]1c773ea12009-04-28 19:58:422871 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162872
2873 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422874 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162875
2876 response = trans->GetResponseInfo();
2877 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2878 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162879}
[email protected]4ddaf2502008-10-23 18:26:192880
[email protected]ea9dc9a2009-09-05 00:43:322881// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2882// can't hook into its internals to cause it to generate predictable NTLM
2883// authorization headers.
2884#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292885// The NTLM authentication unit tests were generated by capturing the HTTP
2886// requests and responses using Fiddler 2 and inspecting the generated random
2887// bytes in the debugger.
2888
2889// Enter the correct password and authenticate successfully.
2890TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422891 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242892 request.method = "GET";
2893 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2894 request.load_flags = 0;
2895
[email protected]cb9bf6ca2011-01-28 13:15:272896 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2897 MockGetHostName);
2898 SessionDependencies session_deps;
2899 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2900
[email protected]3f918782009-02-28 01:29:242901 MockWrite data_writes1[] = {
2902 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2903 "Host: 172.22.68.17\r\n"
2904 "Connection: keep-alive\r\n\r\n"),
2905 };
2906
2907 MockRead data_reads1[] = {
2908 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042909 // Negotiate and NTLM are often requested together. However, we only want
2910 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2911 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242912 MockRead("WWW-Authenticate: NTLM\r\n"),
2913 MockRead("Connection: close\r\n"),
2914 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362915 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242916 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422917 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242918 };
2919
2920 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222921 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242922 // request we should be issuing -- the final header line contains a Type
2923 // 1 message.
2924 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2925 "Host: 172.22.68.17\r\n"
2926 "Connection: keep-alive\r\n"
2927 "Authorization: NTLM "
2928 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2929
2930 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2931 // (the credentials for the origin server). The second request continues
2932 // on the same connection.
2933 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2934 "Host: 172.22.68.17\r\n"
2935 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292936 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2937 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2938 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2939 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2940 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242941 };
2942
2943 MockRead data_reads2[] = {
2944 // The origin server responds with a Type 2 message.
2945 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2946 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292947 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242948 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2949 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2950 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2951 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2952 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2953 "BtAAAAAAA=\r\n"),
2954 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362955 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242956 MockRead("You are not authorized to view this page\r\n"),
2957
2958 // Lastly we get the desired content.
2959 MockRead("HTTP/1.1 200 OK\r\n"),
2960 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2961 MockRead("Content-Length: 13\r\n\r\n"),
2962 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422963 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242964 };
2965
[email protected]31a2bfe2010-02-09 08:03:392966 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2967 data_writes1, arraysize(data_writes1));
2968 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2969 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592970 session_deps.socket_factory.AddSocketDataProvider(&data1);
2971 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242972
[email protected]f1f3f0f82011-10-01 20:38:102973 TestOldCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:242974
[email protected]0b0bf032010-09-21 18:08:502975 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2976
[email protected]5a1d7ca2010-04-28 20:12:272977 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422978 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242979
2980 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422981 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242982
[email protected]0757e7702009-03-27 04:00:222983 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2984
[email protected]1c773ea12009-04-28 19:58:422985 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:042986 ASSERT_FALSE(response == NULL);
2987 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:242988
[email protected]f1f3f0f82011-10-01 20:38:102989 TestOldCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:252990
[email protected]f3cf9802011-10-28 18:44:582991 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
2992 &callback2);
[email protected]10af5fe72011-01-31 16:17:252993 EXPECT_EQ(ERR_IO_PENDING, rv);
2994
2995 rv = callback2.WaitForResult();
2996 EXPECT_EQ(OK, rv);
2997
2998 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2999
3000 response = trans->GetResponseInfo();
3001 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:253002 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3003
[email protected]f1f3f0f82011-10-01 20:38:103004 TestOldCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:243005
[email protected]f3cf9802011-10-28 18:44:583006 rv = trans->RestartWithAuth(AuthCredentials(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423007 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243008
[email protected]0757e7702009-03-27 04:00:223009 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423010 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243011
3012 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503013 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:243014 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3015 EXPECT_EQ(13, response->headers->GetContentLength());
3016}
3017
[email protected]385a4672009-03-11 22:21:293018// Enter a wrong password, and then the correct one.
3019TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:423020 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:293021 request.method = "GET";
3022 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3023 request.load_flags = 0;
3024
[email protected]cb9bf6ca2011-01-28 13:15:273025 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3026 MockGetHostName);
3027 SessionDependencies session_deps;
3028 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3029
[email protected]385a4672009-03-11 22:21:293030 MockWrite data_writes1[] = {
3031 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3032 "Host: 172.22.68.17\r\n"
3033 "Connection: keep-alive\r\n\r\n"),
3034 };
3035
3036 MockRead data_reads1[] = {
3037 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:043038 // Negotiate and NTLM are often requested together. However, we only want
3039 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3040 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:293041 MockRead("WWW-Authenticate: NTLM\r\n"),
3042 MockRead("Connection: close\r\n"),
3043 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363044 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293045 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423046 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293047 };
3048
3049 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:223050 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293051 // request we should be issuing -- the final header line contains a Type
3052 // 1 message.
3053 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3054 "Host: 172.22.68.17\r\n"
3055 "Connection: keep-alive\r\n"
3056 "Authorization: NTLM "
3057 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3058
3059 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3060 // (the credentials for the origin server). The second request continues
3061 // on the same connection.
3062 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3063 "Host: 172.22.68.17\r\n"
3064 "Connection: keep-alive\r\n"
3065 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3066 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3067 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
3068 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
3069 "4Ww7b7E=\r\n\r\n"),
3070 };
3071
3072 MockRead data_reads2[] = {
3073 // The origin server responds with a Type 2 message.
3074 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3075 MockRead("WWW-Authenticate: NTLM "
3076 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
3077 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3078 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3079 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3080 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3081 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3082 "BtAAAAAAA=\r\n"),
3083 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363084 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293085 MockRead("You are not authorized to view this page\r\n"),
3086
3087 // Wrong password.
3088 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:293089 MockRead("WWW-Authenticate: NTLM\r\n"),
3090 MockRead("Connection: close\r\n"),
3091 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363092 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293093 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423094 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293095 };
3096
3097 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223098 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293099 // request we should be issuing -- the final header line contains a Type
3100 // 1 message.
3101 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3102 "Host: 172.22.68.17\r\n"
3103 "Connection: keep-alive\r\n"
3104 "Authorization: NTLM "
3105 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3106
3107 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3108 // (the credentials for the origin server). The second request continues
3109 // on the same connection.
3110 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3111 "Host: 172.22.68.17\r\n"
3112 "Connection: keep-alive\r\n"
3113 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3114 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3115 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3116 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3117 "+4MUm7c=\r\n\r\n"),
3118 };
3119
3120 MockRead data_reads3[] = {
3121 // The origin server responds with a Type 2 message.
3122 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3123 MockRead("WWW-Authenticate: NTLM "
3124 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3125 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3126 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3127 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3128 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3129 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3130 "BtAAAAAAA=\r\n"),
3131 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363132 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293133 MockRead("You are not authorized to view this page\r\n"),
3134
3135 // Lastly we get the desired content.
3136 MockRead("HTTP/1.1 200 OK\r\n"),
3137 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3138 MockRead("Content-Length: 13\r\n\r\n"),
3139 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423140 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293141 };
3142
[email protected]31a2bfe2010-02-09 08:03:393143 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3144 data_writes1, arraysize(data_writes1));
3145 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3146 data_writes2, arraysize(data_writes2));
3147 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3148 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593149 session_deps.socket_factory.AddSocketDataProvider(&data1);
3150 session_deps.socket_factory.AddSocketDataProvider(&data2);
3151 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293152
[email protected]f1f3f0f82011-10-01 20:38:103153 TestOldCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:293154
[email protected]0b0bf032010-09-21 18:08:503155 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3156
[email protected]5a1d7ca2010-04-28 20:12:273157 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423158 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293159
3160 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423161 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293162
[email protected]0757e7702009-03-27 04:00:223163 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293164
[email protected]1c773ea12009-04-28 19:58:423165 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503166 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043167 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:293168
[email protected]f1f3f0f82011-10-01 20:38:103169 TestOldCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293170
[email protected]0757e7702009-03-27 04:00:223171 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:583172 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
3173 &callback2);
[email protected]1c773ea12009-04-28 19:58:423174 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293175
[email protected]10af5fe72011-01-31 16:17:253176 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423177 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293178
[email protected]0757e7702009-03-27 04:00:223179 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:103180 TestOldCompletionCallback callback3;
[email protected]f3cf9802011-10-28 18:44:583181 rv = trans->RestartWithAuth(AuthCredentials(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423182 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253183 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423184 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223185 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3186
3187 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043188 ASSERT_FALSE(response == NULL);
3189 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:223190
[email protected]f1f3f0f82011-10-01 20:38:103191 TestOldCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223192
3193 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:583194 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
3195 &callback4);
[email protected]10af5fe72011-01-31 16:17:253196 EXPECT_EQ(ERR_IO_PENDING, rv);
3197
3198 rv = callback4.WaitForResult();
3199 EXPECT_EQ(OK, rv);
3200
3201 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3202
[email protected]f1f3f0f82011-10-01 20:38:103203 TestOldCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:253204
3205 // One more roundtrip
[email protected]f3cf9802011-10-28 18:44:583206 rv = trans->RestartWithAuth(AuthCredentials(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423207 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223208
3209 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423210 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223211
[email protected]385a4672009-03-11 22:21:293212 response = trans->GetResponseInfo();
3213 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3214 EXPECT_EQ(13, response->headers->GetContentLength());
3215}
[email protected]ea9dc9a2009-09-05 00:43:323216#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293217
[email protected]4ddaf2502008-10-23 18:26:193218// Test reading a server response which has only headers, and no body.
3219// After some maximum number of bytes is consumed, the transaction should
3220// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3221TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423222 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193223 request.method = "GET";
3224 request.url = GURL("http://www.google.com/");
3225 request.load_flags = 0;
3226
[email protected]cb9bf6ca2011-01-28 13:15:273227 SessionDependencies session_deps;
3228 scoped_ptr<HttpTransaction> trans(
3229 new HttpNetworkTransaction(CreateSession(&session_deps)));
3230
[email protected]b75b7b2f2009-10-06 00:54:533231 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433232 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533233 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193234
3235 MockRead data_reads[] = {
3236 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433237 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193238 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423239 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193240 };
[email protected]31a2bfe2010-02-09 08:03:393241 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593242 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193243
[email protected]f1f3f0f82011-10-01 20:38:103244 TestOldCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:193245
[email protected]5a1d7ca2010-04-28 20:12:273246 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423247 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193248
3249 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423250 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193251
[email protected]1c773ea12009-04-28 19:58:423252 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193253 EXPECT_TRUE(response == NULL);
3254}
[email protected]f4e426b2008-11-05 00:24:493255
3256// Make sure that we don't try to reuse a TCPClientSocket when failing to
3257// establish tunnel.
3258// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283259TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273260 HttpRequestInfo request;
3261 request.method = "GET";
3262 request.url = GURL("https://www.google.com/");
3263 request.load_flags = 0;
3264
[email protected]f4e426b2008-11-05 00:24:493265 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003266 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013267
[email protected]228ff742009-06-05 01:19:593268 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493269
[email protected]5695b8c2009-09-30 21:36:433270 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493271
[email protected]f4e426b2008-11-05 00:24:493272 // Since we have proxy, should try to establish tunnel.
3273 MockWrite data_writes1[] = {
3274 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453275 "Host: www.google.com\r\n"
3276 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493277 };
3278
[email protected]77848d12008-11-14 00:00:223279 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493280 // connection. Usually a proxy would return 501 (not implemented),
3281 // or 200 (tunnel established).
3282 MockRead data_reads1[] = {
3283 MockRead("HTTP/1.1 404 Not Found\r\n"),
3284 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423285 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493286 };
3287
[email protected]31a2bfe2010-02-09 08:03:393288 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3289 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593290 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493291
[email protected]f1f3f0f82011-10-01 20:38:103292 TestOldCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:493293
[email protected]5a1d7ca2010-04-28 20:12:273294 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423295 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493296
3297 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423298 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493299
[email protected]1c773ea12009-04-28 19:58:423300 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083301 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493302
[email protected]b4404c02009-04-10 16:38:523303 // Empty the current queue. This is necessary because idle sockets are
3304 // added to the connection pool asynchronously with a PostTask.
3305 MessageLoop::current()->RunAllPending();
3306
[email protected]f4e426b2008-11-05 00:24:493307 // We now check to make sure the TCPClientSocket was not added back to
3308 // the pool.
[email protected]ab739042011-04-07 15:22:283309 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493310 trans.reset();
[email protected]b4404c02009-04-10 16:38:523311 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493312 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]ab739042011-04-07 15:22:283313 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493314}
[email protected]372d34a2008-11-05 21:30:513315
[email protected]1b157c02009-04-21 01:55:403316// Make sure that we recycle a socket after reading all of the response body.
3317TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423318 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403319 request.method = "GET";
3320 request.url = GURL("http://www.google.com/");
3321 request.load_flags = 0;
3322
[email protected]cb9bf6ca2011-01-28 13:15:273323 SessionDependencies session_deps;
3324 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3325
3326 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3327
[email protected]1b157c02009-04-21 01:55:403328 MockRead data_reads[] = {
3329 // A part of the response body is received with the response headers.
3330 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3331 // The rest of the response body is received in two parts.
3332 MockRead("lo"),
3333 MockRead(" world"),
3334 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423335 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403336 };
3337
[email protected]31a2bfe2010-02-09 08:03:393338 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593339 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403340
[email protected]f1f3f0f82011-10-01 20:38:103341 TestOldCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:403342
[email protected]5a1d7ca2010-04-28 20:12:273343 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423344 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403345
3346 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423347 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403348
[email protected]1c773ea12009-04-28 19:58:423349 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503350 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:403351
3352 EXPECT_TRUE(response->headers != NULL);
3353 std::string status_line = response->headers->GetStatusLine();
3354 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3355
[email protected]ab739042011-04-07 15:22:283356 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403357
3358 std::string response_data;
3359 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423360 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403361 EXPECT_EQ("hello world", response_data);
3362
3363 // Empty the current queue. This is necessary because idle sockets are
3364 // added to the connection pool asynchronously with a PostTask.
3365 MessageLoop::current()->RunAllPending();
3366
3367 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283368 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403369}
3370
[email protected]76a505b2010-08-25 06:23:003371// Make sure that we recycle a SSL socket after reading all of the response
3372// body.
3373TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3374 SessionDependencies session_deps;
3375 HttpRequestInfo request;
3376 request.method = "GET";
3377 request.url = GURL("https://www.google.com/");
3378 request.load_flags = 0;
3379
3380 MockWrite data_writes[] = {
3381 MockWrite("GET / HTTP/1.1\r\n"
3382 "Host: www.google.com\r\n"
3383 "Connection: keep-alive\r\n\r\n"),
3384 };
3385
3386 MockRead data_reads[] = {
3387 MockRead("HTTP/1.1 200 OK\r\n"),
3388 MockRead("Content-Length: 11\r\n\r\n"),
3389 MockRead("hello world"),
3390 MockRead(false, OK),
3391 };
3392
3393 SSLSocketDataProvider ssl(true, OK);
3394 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3395
3396 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3397 data_writes, arraysize(data_writes));
3398 session_deps.socket_factory.AddSocketDataProvider(&data);
3399
[email protected]f1f3f0f82011-10-01 20:38:103400 TestOldCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003401
3402 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3403 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3404
3405 int rv = trans->Start(&request, &callback, BoundNetLog());
3406
3407 EXPECT_EQ(ERR_IO_PENDING, rv);
3408 EXPECT_EQ(OK, callback.WaitForResult());
3409
3410 const HttpResponseInfo* response = trans->GetResponseInfo();
3411 ASSERT_TRUE(response != NULL);
3412 ASSERT_TRUE(response->headers != NULL);
3413 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3414
[email protected]ab739042011-04-07 15:22:283415 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003416
3417 std::string response_data;
3418 rv = ReadTransaction(trans.get(), &response_data);
3419 EXPECT_EQ(OK, rv);
3420 EXPECT_EQ("hello world", response_data);
3421
3422 // Empty the current queue. This is necessary because idle sockets are
3423 // added to the connection pool asynchronously with a PostTask.
3424 MessageLoop::current()->RunAllPending();
3425
3426 // We now check to make sure the socket was added back to the pool.
3427 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3428}
3429
3430// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3431// from the pool and make sure that we recover okay.
3432TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3433 SessionDependencies session_deps;
3434 HttpRequestInfo request;
3435 request.method = "GET";
3436 request.url = GURL("https://www.google.com/");
3437 request.load_flags = 0;
3438
3439 MockWrite data_writes[] = {
3440 MockWrite("GET / HTTP/1.1\r\n"
3441 "Host: www.google.com\r\n"
3442 "Connection: keep-alive\r\n\r\n"),
3443 MockWrite("GET / HTTP/1.1\r\n"
3444 "Host: www.google.com\r\n"
3445 "Connection: keep-alive\r\n\r\n"),
3446 };
3447
3448 MockRead data_reads[] = {
3449 MockRead("HTTP/1.1 200 OK\r\n"),
3450 MockRead("Content-Length: 11\r\n\r\n"),
3451 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3452 MockRead("hello world"),
3453 MockRead(true, 0, 0) // EOF
3454 };
3455
3456 SSLSocketDataProvider ssl(true, OK);
3457 SSLSocketDataProvider ssl2(true, OK);
3458 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3459 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3460
3461 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3462 data_writes, arraysize(data_writes));
3463 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3464 data_writes, arraysize(data_writes));
3465 session_deps.socket_factory.AddSocketDataProvider(&data);
3466 session_deps.socket_factory.AddSocketDataProvider(&data2);
3467
[email protected]f1f3f0f82011-10-01 20:38:103468 TestOldCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003469
3470 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3471 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3472
3473 int rv = trans->Start(&request, &callback, BoundNetLog());
3474
3475 EXPECT_EQ(ERR_IO_PENDING, rv);
3476 EXPECT_EQ(OK, callback.WaitForResult());
3477
3478 const HttpResponseInfo* response = trans->GetResponseInfo();
3479 ASSERT_TRUE(response != NULL);
3480 ASSERT_TRUE(response->headers != NULL);
3481 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3482
[email protected]ab739042011-04-07 15:22:283483 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003484
3485 std::string response_data;
3486 rv = ReadTransaction(trans.get(), &response_data);
3487 EXPECT_EQ(OK, rv);
3488 EXPECT_EQ("hello world", response_data);
3489
3490 // Empty the current queue. This is necessary because idle sockets are
3491 // added to the connection pool asynchronously with a PostTask.
3492 MessageLoop::current()->RunAllPending();
3493
3494 // We now check to make sure the socket was added back to the pool.
3495 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3496
3497 // Now start the second transaction, which should reuse the previous socket.
3498
3499 trans.reset(new HttpNetworkTransaction(session));
3500
3501 rv = trans->Start(&request, &callback, BoundNetLog());
3502
3503 EXPECT_EQ(ERR_IO_PENDING, rv);
3504 EXPECT_EQ(OK, callback.WaitForResult());
3505
3506 response = trans->GetResponseInfo();
3507 ASSERT_TRUE(response != NULL);
3508 ASSERT_TRUE(response->headers != NULL);
3509 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3510
[email protected]ab739042011-04-07 15:22:283511 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003512
3513 rv = ReadTransaction(trans.get(), &response_data);
3514 EXPECT_EQ(OK, rv);
3515 EXPECT_EQ("hello world", response_data);
3516
3517 // Empty the current queue. This is necessary because idle sockets are
3518 // added to the connection pool asynchronously with a PostTask.
3519 MessageLoop::current()->RunAllPending();
3520
3521 // We now check to make sure the socket was added back to the pool.
3522 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3523}
3524
[email protected]b4404c02009-04-10 16:38:523525// Make sure that we recycle a socket after a zero-length response.
3526// http://crbug.com/9880
3527TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423528 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523529 request.method = "GET";
3530 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3531 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3532 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3533 "rt=prt.2642,ol.2649,xjs.2951");
3534 request.load_flags = 0;
3535
[email protected]cb9bf6ca2011-01-28 13:15:273536 SessionDependencies session_deps;
3537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3538
3539 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3540
[email protected]b4404c02009-04-10 16:38:523541 MockRead data_reads[] = {
3542 MockRead("HTTP/1.1 204 No Content\r\n"
3543 "Content-Length: 0\r\n"
3544 "Content-Type: text/html\r\n\r\n"),
3545 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423546 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523547 };
3548
[email protected]31a2bfe2010-02-09 08:03:393549 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593550 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523551
[email protected]f1f3f0f82011-10-01 20:38:103552 TestOldCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:523553
[email protected]5a1d7ca2010-04-28 20:12:273554 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423555 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523556
3557 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423558 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523559
[email protected]1c773ea12009-04-28 19:58:423560 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503561 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:523562
3563 EXPECT_TRUE(response->headers != NULL);
3564 std::string status_line = response->headers->GetStatusLine();
3565 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3566
[email protected]ab739042011-04-07 15:22:283567 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523568
3569 std::string response_data;
3570 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423571 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523572 EXPECT_EQ("", response_data);
3573
3574 // Empty the current queue. This is necessary because idle sockets are
3575 // added to the connection pool asynchronously with a PostTask.
3576 MessageLoop::current()->RunAllPending();
3577
3578 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283579 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523580}
3581
[email protected]372d34a2008-11-05 21:30:513582TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423583 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513584 // Transaction 1: a GET request that succeeds. The socket is recycled
3585 // after use.
3586 request[0].method = "GET";
3587 request[0].url = GURL("http://www.google.com/");
3588 request[0].load_flags = 0;
3589 // Transaction 2: a POST request. Reuses the socket kept alive from
3590 // transaction 1. The first attempts fails when writing the POST data.
3591 // This causes the transaction to retry with a new socket. The second
3592 // attempt succeeds.
3593 request[1].method = "POST";
3594 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423595 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513596 request[1].upload_data->AppendBytes("foo", 3);
3597 request[1].load_flags = 0;
3598
[email protected]228ff742009-06-05 01:19:593599 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513601
3602 // The first socket is used for transaction 1 and the first attempt of
3603 // transaction 2.
3604
3605 // The response of transaction 1.
3606 MockRead data_reads1[] = {
3607 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3608 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423609 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513610 };
3611 // The mock write results of transaction 1 and the first attempt of
3612 // transaction 2.
3613 MockWrite data_writes1[] = {
3614 MockWrite(false, 64), // GET
3615 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423616 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513617 };
[email protected]31a2bfe2010-02-09 08:03:393618 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3619 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513620
3621 // The second socket is used for the second attempt of transaction 2.
3622
3623 // The response of transaction 2.
3624 MockRead data_reads2[] = {
3625 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3626 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423627 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513628 };
3629 // The mock write results of the second attempt of transaction 2.
3630 MockWrite data_writes2[] = {
3631 MockWrite(false, 93), // POST
3632 MockWrite(false, 3), // POST data
3633 };
[email protected]31a2bfe2010-02-09 08:03:393634 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3635 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513636
[email protected]5ecc992a42009-11-11 01:41:593637 session_deps.socket_factory.AddSocketDataProvider(&data1);
3638 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513639
3640 const char* kExpectedResponseData[] = {
3641 "hello world", "welcome"
3642 };
3643
3644 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423645 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433646 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513647
[email protected]f1f3f0f82011-10-01 20:38:103648 TestOldCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:513649
[email protected]5a1d7ca2010-04-28 20:12:273650 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423651 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513652
3653 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423654 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513655
[email protected]1c773ea12009-04-28 19:58:423656 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503657 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:513658
3659 EXPECT_TRUE(response->headers != NULL);
3660 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3661
3662 std::string response_data;
3663 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423664 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513665 EXPECT_EQ(kExpectedResponseData[i], response_data);
3666 }
3667}
[email protected]f9ee6b52008-11-08 06:46:233668
3669// Test the request-challenge-retry sequence for basic auth when there is
3670// an identity in the URL. The request should be sent as normal, but when
3671// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323672TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423673 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233674 request.method = "GET";
3675 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293676 request.url = GURL("http://foo:b@[email protected]/");
3677
[email protected]cb9bf6ca2011-01-28 13:15:273678 SessionDependencies session_deps;
3679 scoped_ptr<HttpTransaction> trans(
3680 new HttpNetworkTransaction(CreateSession(&session_deps)));
3681
[email protected]a97cca42009-08-14 01:00:293682 // The password contains an escaped character -- for this test to pass it
3683 // will need to be unescaped by HttpNetworkTransaction.
3684 EXPECT_EQ("b%40r", request.url.password());
3685
[email protected]ea9dc9a2009-09-05 00:43:323686 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233687
3688 MockWrite data_writes1[] = {
3689 MockWrite("GET / HTTP/1.1\r\n"
3690 "Host: www.google.com\r\n"
3691 "Connection: keep-alive\r\n\r\n"),
3692 };
3693
3694 MockRead data_reads1[] = {
3695 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3696 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3697 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423698 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233699 };
3700
3701 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323702 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233703 MockWrite data_writes2[] = {
3704 MockWrite("GET / HTTP/1.1\r\n"
3705 "Host: www.google.com\r\n"
3706 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293707 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233708 };
3709
3710 MockRead data_reads2[] = {
3711 MockRead("HTTP/1.0 200 OK\r\n"),
3712 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423713 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233714 };
3715
[email protected]31a2bfe2010-02-09 08:03:393716 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3717 data_writes1, arraysize(data_writes1));
3718 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3719 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593720 session_deps.socket_factory.AddSocketDataProvider(&data1);
3721 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233722
[email protected]f1f3f0f82011-10-01 20:38:103723 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233724
[email protected]5a1d7ca2010-04-28 20:12:273725 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423726 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233727
3728 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423729 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233730
[email protected]0757e7702009-03-27 04:00:223731 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:103732 TestOldCompletionCallback callback2;
[email protected]f3cf9802011-10-28 18:44:583733 rv = trans->RestartWithAuth(AuthCredentials(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423734 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223735 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423736 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223737 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3738
[email protected]1c773ea12009-04-28 19:58:423739 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503740 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233741
3742 // There is no challenge info, since the identity in URL worked.
3743 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3744
3745 EXPECT_EQ(100, response->headers->GetContentLength());
3746
3747 // Empty the current queue.
3748 MessageLoop::current()->RunAllPending();
3749}
3750
[email protected]ea9dc9a2009-09-05 00:43:323751// Test the request-challenge-retry sequence for basic auth when there is
3752// an incorrect identity in the URL. The identity from the URL should be used
3753// only once.
3754TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323755 HttpRequestInfo request;
3756 request.method = "GET";
3757 // Note: the URL has a username:password in it. The password "baz" is
3758 // wrong (should be "bar").
3759 request.url = GURL("http://foo:[email protected]/");
3760
3761 request.load_flags = LOAD_NORMAL;
3762
[email protected]cb9bf6ca2011-01-28 13:15:273763 SessionDependencies session_deps;
3764 scoped_ptr<HttpTransaction> trans(
3765 new HttpNetworkTransaction(CreateSession(&session_deps)));
3766
[email protected]ea9dc9a2009-09-05 00:43:323767 MockWrite data_writes1[] = {
3768 MockWrite("GET / HTTP/1.1\r\n"
3769 "Host: www.google.com\r\n"
3770 "Connection: keep-alive\r\n\r\n"),
3771 };
3772
3773 MockRead data_reads1[] = {
3774 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3775 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3776 MockRead("Content-Length: 10\r\n\r\n"),
3777 MockRead(false, ERR_FAILED),
3778 };
3779
3780 // After the challenge above, the transaction will be restarted using the
3781 // identity from the url (foo, baz) to answer the challenge.
3782 MockWrite data_writes2[] = {
3783 MockWrite("GET / HTTP/1.1\r\n"
3784 "Host: www.google.com\r\n"
3785 "Connection: keep-alive\r\n"
3786 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3787 };
3788
3789 MockRead data_reads2[] = {
3790 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3791 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3792 MockRead("Content-Length: 10\r\n\r\n"),
3793 MockRead(false, ERR_FAILED),
3794 };
3795
3796 // After the challenge above, the transaction will be restarted using the
3797 // identity supplied by the user (foo, bar) to answer the challenge.
3798 MockWrite data_writes3[] = {
3799 MockWrite("GET / HTTP/1.1\r\n"
3800 "Host: www.google.com\r\n"
3801 "Connection: keep-alive\r\n"
3802 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3803 };
3804
3805 MockRead data_reads3[] = {
3806 MockRead("HTTP/1.0 200 OK\r\n"),
3807 MockRead("Content-Length: 100\r\n\r\n"),
3808 MockRead(false, OK),
3809 };
3810
[email protected]31a2bfe2010-02-09 08:03:393811 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3812 data_writes1, arraysize(data_writes1));
3813 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3814 data_writes2, arraysize(data_writes2));
3815 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3816 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593817 session_deps.socket_factory.AddSocketDataProvider(&data1);
3818 session_deps.socket_factory.AddSocketDataProvider(&data2);
3819 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323820
[email protected]f1f3f0f82011-10-01 20:38:103821 TestOldCompletionCallback callback1;
[email protected]ea9dc9a2009-09-05 00:43:323822
[email protected]5a1d7ca2010-04-28 20:12:273823 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323824 EXPECT_EQ(ERR_IO_PENDING, rv);
3825
3826 rv = callback1.WaitForResult();
3827 EXPECT_EQ(OK, rv);
3828
3829 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:103830 TestOldCompletionCallback callback2;
[email protected]f3cf9802011-10-28 18:44:583831 rv = trans->RestartWithAuth(AuthCredentials(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323832 EXPECT_EQ(ERR_IO_PENDING, rv);
3833 rv = callback2.WaitForResult();
3834 EXPECT_EQ(OK, rv);
3835 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3836
3837 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503838 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043839 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]ea9dc9a2009-09-05 00:43:323840
[email protected]f1f3f0f82011-10-01 20:38:103841 TestOldCompletionCallback callback3;
[email protected]f3cf9802011-10-28 18:44:583842 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323843 EXPECT_EQ(ERR_IO_PENDING, rv);
3844 rv = callback3.WaitForResult();
3845 EXPECT_EQ(OK, rv);
3846 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3847
3848 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503849 ASSERT_TRUE(response != NULL);
[email protected]ea9dc9a2009-09-05 00:43:323850
3851 // There is no challenge info, since the identity worked.
3852 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3853
3854 EXPECT_EQ(100, response->headers->GetContentLength());
3855
3856 // Empty the current queue.
3857 MessageLoop::current()->RunAllPending();
3858}
3859
[email protected]f9ee6b52008-11-08 06:46:233860// Test that previously tried username/passwords for a realm get re-used.
3861TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593862 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273863 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233864
3865 // Transaction 1: authenticate (foo, bar) on MyRealm1
3866 {
[email protected]1c773ea12009-04-28 19:58:423867 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233868 request.method = "GET";
3869 request.url = GURL("http://www.google.com/x/y/z");
3870 request.load_flags = 0;
3871
[email protected]cb9bf6ca2011-01-28 13:15:273872 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3873
[email protected]f9ee6b52008-11-08 06:46:233874 MockWrite data_writes1[] = {
3875 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3876 "Host: www.google.com\r\n"
3877 "Connection: keep-alive\r\n\r\n"),
3878 };
3879
3880 MockRead data_reads1[] = {
3881 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3882 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3883 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423884 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233885 };
3886
3887 // Resend with authorization (username=foo, password=bar)
3888 MockWrite data_writes2[] = {
3889 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3890 "Host: www.google.com\r\n"
3891 "Connection: keep-alive\r\n"
3892 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3893 };
3894
3895 // Sever accepts the authorization.
3896 MockRead data_reads2[] = {
3897 MockRead("HTTP/1.0 200 OK\r\n"),
3898 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423899 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233900 };
3901
[email protected]31a2bfe2010-02-09 08:03:393902 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3903 data_writes1, arraysize(data_writes1));
3904 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3905 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593906 session_deps.socket_factory.AddSocketDataProvider(&data1);
3907 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233908
[email protected]f1f3f0f82011-10-01 20:38:103909 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233910
[email protected]5a1d7ca2010-04-28 20:12:273911 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423912 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233913
3914 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423915 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233916
[email protected]1c773ea12009-04-28 19:58:423917 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503918 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043919 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:233920
[email protected]f1f3f0f82011-10-01 20:38:103921 TestOldCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233922
[email protected]f3cf9802011-10-28 18:44:583923 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]1c773ea12009-04-28 19:58:423924 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233925
3926 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423927 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233928
3929 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503930 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233931 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3932 EXPECT_EQ(100, response->headers->GetContentLength());
3933 }
3934
3935 // ------------------------------------------------------------------------
3936
3937 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3938 {
[email protected]1c773ea12009-04-28 19:58:423939 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233940 request.method = "GET";
3941 // Note that Transaction 1 was at /x/y/z, so this is in the same
3942 // protection space as MyRealm1.
3943 request.url = GURL("http://www.google.com/x/y/a/b");
3944 request.load_flags = 0;
3945
[email protected]cb9bf6ca2011-01-28 13:15:273946 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3947
[email protected]f9ee6b52008-11-08 06:46:233948 MockWrite data_writes1[] = {
3949 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3950 "Host: www.google.com\r\n"
3951 "Connection: keep-alive\r\n"
3952 // Send preemptive authorization for MyRealm1
3953 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3954 };
3955
3956 // The server didn't like the preemptive authorization, and
3957 // challenges us for a different realm (MyRealm2).
3958 MockRead data_reads1[] = {
3959 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3960 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3961 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423962 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233963 };
3964
3965 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3966 MockWrite data_writes2[] = {
3967 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3968 "Host: www.google.com\r\n"
3969 "Connection: keep-alive\r\n"
3970 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3971 };
3972
3973 // Sever accepts the authorization.
3974 MockRead data_reads2[] = {
3975 MockRead("HTTP/1.0 200 OK\r\n"),
3976 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423977 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233978 };
3979
[email protected]31a2bfe2010-02-09 08:03:393980 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3981 data_writes1, arraysize(data_writes1));
3982 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3983 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593984 session_deps.socket_factory.AddSocketDataProvider(&data1);
3985 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233986
[email protected]f1f3f0f82011-10-01 20:38:103987 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233988
[email protected]5a1d7ca2010-04-28 20:12:273989 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423990 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233991
3992 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423993 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233994
[email protected]1c773ea12009-04-28 19:58:423995 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503996 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043997 ASSERT_TRUE(response->auth_challenge.get());
3998 EXPECT_FALSE(response->auth_challenge->is_proxy);
3999 EXPECT_EQ("www.google.com:80",
4000 response->auth_challenge->challenger.ToString());
4001 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
4002 EXPECT_EQ("basic", response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:234003
[email protected]f1f3f0f82011-10-01 20:38:104004 TestOldCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:234005
[email protected]f3cf9802011-10-28 18:44:584006 rv = trans->RestartWithAuth(AuthCredentials(kFoo2, kBar2), &callback2);
[email protected]1c773ea12009-04-28 19:58:424007 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234008
4009 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424010 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234011
4012 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504013 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234014 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4015 EXPECT_EQ(100, response->headers->GetContentLength());
4016 }
4017
4018 // ------------------------------------------------------------------------
4019
4020 // Transaction 3: Resend a request in MyRealm's protection space --
4021 // succeed with preemptive authorization.
4022 {
[email protected]1c773ea12009-04-28 19:58:424023 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234024 request.method = "GET";
4025 request.url = GURL("http://www.google.com/x/y/z2");
4026 request.load_flags = 0;
4027
[email protected]cb9bf6ca2011-01-28 13:15:274028 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4029
[email protected]f9ee6b52008-11-08 06:46:234030 MockWrite data_writes1[] = {
4031 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
4032 "Host: www.google.com\r\n"
4033 "Connection: keep-alive\r\n"
4034 // The authorization for MyRealm1 gets sent preemptively
4035 // (since the url is in the same protection space)
4036 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4037 };
4038
4039 // Sever accepts the preemptive authorization
4040 MockRead data_reads1[] = {
4041 MockRead("HTTP/1.0 200 OK\r\n"),
4042 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424043 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234044 };
4045
[email protected]31a2bfe2010-02-09 08:03:394046 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4047 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594048 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:234049
[email protected]f1f3f0f82011-10-01 20:38:104050 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234051
[email protected]5a1d7ca2010-04-28 20:12:274052 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424053 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234054
4055 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424056 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234057
[email protected]1c773ea12009-04-28 19:58:424058 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504059 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234060
4061 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4062 EXPECT_EQ(100, response->headers->GetContentLength());
4063 }
4064
4065 // ------------------------------------------------------------------------
4066
4067 // Transaction 4: request another URL in MyRealm (however the
4068 // url is not known to belong to the protection space, so no pre-auth).
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/x/1");
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 /x/1 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 MyRealm's cache.
4091 MockWrite data_writes2[] = {
4092 MockWrite("GET /x/1 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 accepts the authorization.
4099 MockRead data_reads2[] = {
4100 MockRead("HTTP/1.0 200 OK\r\n"),
4101 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424102 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234103 };
4104
[email protected]31a2bfe2010-02-09 08:03:394105 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4106 data_writes1, arraysize(data_writes1));
4107 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4108 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594109 session_deps.socket_factory.AddSocketDataProvider(&data1);
4110 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234111
[email protected]f1f3f0f82011-10-01 20:38:104112 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234113
[email protected]5a1d7ca2010-04-28 20:12:274114 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424115 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234116
4117 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424118 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234119
[email protected]0757e7702009-03-27 04:00:224120 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:104121 TestOldCompletionCallback callback2;
[email protected]f3cf9802011-10-28 18:44:584122 rv = trans->RestartWithAuth(AuthCredentials(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424123 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224124 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424125 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224126 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4127
[email protected]1c773ea12009-04-28 19:58:424128 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504129 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234130 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4131 EXPECT_EQ(100, response->headers->GetContentLength());
4132 }
4133
4134 // ------------------------------------------------------------------------
4135
4136 // Transaction 5: request a URL in MyRealm, but the server rejects the
4137 // cached identity. Should invalidate and re-prompt.
4138 {
[email protected]1c773ea12009-04-28 19:58:424139 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234140 request.method = "GET";
4141 request.url = GURL("http://www.google.com/p/q/t");
4142 request.load_flags = 0;
4143
[email protected]cb9bf6ca2011-01-28 13:15:274144 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4145
[email protected]f9ee6b52008-11-08 06:46:234146 MockWrite data_writes1[] = {
4147 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4148 "Host: www.google.com\r\n"
4149 "Connection: keep-alive\r\n\r\n"),
4150 };
4151
4152 MockRead data_reads1[] = {
4153 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4154 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4155 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424156 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234157 };
4158
4159 // Resend with authorization from cache for MyRealm.
4160 MockWrite data_writes2[] = {
4161 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4162 "Host: www.google.com\r\n"
4163 "Connection: keep-alive\r\n"
4164 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4165 };
4166
4167 // Sever rejects the authorization.
4168 MockRead data_reads2[] = {
4169 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4170 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4171 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424172 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234173 };
4174
4175 // At this point we should prompt for new credentials for MyRealm.
4176 // Restart with username=foo3, password=foo4.
4177 MockWrite data_writes3[] = {
4178 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4179 "Host: www.google.com\r\n"
4180 "Connection: keep-alive\r\n"
4181 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4182 };
4183
4184 // Sever accepts the authorization.
4185 MockRead data_reads3[] = {
4186 MockRead("HTTP/1.0 200 OK\r\n"),
4187 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424188 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234189 };
4190
[email protected]31a2bfe2010-02-09 08:03:394191 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4192 data_writes1, arraysize(data_writes1));
4193 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4194 data_writes2, arraysize(data_writes2));
4195 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4196 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594197 session_deps.socket_factory.AddSocketDataProvider(&data1);
4198 session_deps.socket_factory.AddSocketDataProvider(&data2);
4199 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234200
[email protected]f1f3f0f82011-10-01 20:38:104201 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234202
[email protected]5a1d7ca2010-04-28 20:12:274203 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424204 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234205
4206 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424207 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234208
[email protected]0757e7702009-03-27 04:00:224209 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:104210 TestOldCompletionCallback callback2;
[email protected]f3cf9802011-10-28 18:44:584211 rv = trans->RestartWithAuth(AuthCredentials(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424212 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224213 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424214 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224215 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4216
[email protected]1c773ea12009-04-28 19:58:424217 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504218 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044219 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:234220
[email protected]f1f3f0f82011-10-01 20:38:104221 TestOldCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234222
[email protected]f3cf9802011-10-28 18:44:584223 rv = trans->RestartWithAuth(AuthCredentials(kFoo3, kBar3), &callback3);
[email protected]1c773ea12009-04-28 19:58:424224 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234225
[email protected]0757e7702009-03-27 04:00:224226 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424227 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234228
4229 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504230 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234231 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4232 EXPECT_EQ(100, response->headers->GetContentLength());
4233 }
4234}
[email protected]89ceba9a2009-03-21 03:46:064235
[email protected]3c32c5f2010-05-18 15:18:124236// Tests that nonce count increments when multiple auth attempts
4237// are started with the same nonce.
4238TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4239 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444240 HttpAuthHandlerDigest::Factory* digest_factory =
4241 new HttpAuthHandlerDigest::Factory();
4242 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4243 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4244 digest_factory->set_nonce_generator(nonce_generator);
4245 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274246 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124247
4248 // Transaction 1: authenticate (foo, bar) on MyRealm1
4249 {
[email protected]3c32c5f2010-05-18 15:18:124250 HttpRequestInfo request;
4251 request.method = "GET";
4252 request.url = GURL("http://www.google.com/x/y/z");
4253 request.load_flags = 0;
4254
[email protected]cb9bf6ca2011-01-28 13:15:274255 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4256
[email protected]3c32c5f2010-05-18 15:18:124257 MockWrite data_writes1[] = {
4258 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4259 "Host: www.google.com\r\n"
4260 "Connection: keep-alive\r\n\r\n"),
4261 };
4262
4263 MockRead data_reads1[] = {
4264 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4265 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4266 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4267 MockRead(false, OK),
4268 };
4269
4270 // Resend with authorization (username=foo, password=bar)
4271 MockWrite data_writes2[] = {
4272 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4273 "Host: www.google.com\r\n"
4274 "Connection: keep-alive\r\n"
4275 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4276 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4277 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4278 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4279 };
4280
4281 // Sever accepts the authorization.
4282 MockRead data_reads2[] = {
4283 MockRead("HTTP/1.0 200 OK\r\n"),
4284 MockRead(false, OK),
4285 };
4286
4287 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4288 data_writes1, arraysize(data_writes1));
4289 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4290 data_writes2, arraysize(data_writes2));
4291 session_deps.socket_factory.AddSocketDataProvider(&data1);
4292 session_deps.socket_factory.AddSocketDataProvider(&data2);
4293
[email protected]f1f3f0f82011-10-01 20:38:104294 TestOldCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124295
4296 int rv = trans->Start(&request, &callback1, BoundNetLog());
4297 EXPECT_EQ(ERR_IO_PENDING, rv);
4298
4299 rv = callback1.WaitForResult();
4300 EXPECT_EQ(OK, rv);
4301
4302 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504303 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044304 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:124305
[email protected]f1f3f0f82011-10-01 20:38:104306 TestOldCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:124307
[email protected]f3cf9802011-10-28 18:44:584308 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]3c32c5f2010-05-18 15:18:124309 EXPECT_EQ(ERR_IO_PENDING, rv);
4310
4311 rv = callback2.WaitForResult();
4312 EXPECT_EQ(OK, rv);
4313
4314 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504315 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124316 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4317 }
4318
4319 // ------------------------------------------------------------------------
4320
4321 // Transaction 2: Request another resource in digestive's protection space.
4322 // This will preemptively add an Authorization header which should have an
4323 // "nc" value of 2 (as compared to 1 in the first use.
4324 {
[email protected]3c32c5f2010-05-18 15:18:124325 HttpRequestInfo request;
4326 request.method = "GET";
4327 // Note that Transaction 1 was at /x/y/z, so this is in the same
4328 // protection space as digest.
4329 request.url = GURL("http://www.google.com/x/y/a/b");
4330 request.load_flags = 0;
4331
[email protected]cb9bf6ca2011-01-28 13:15:274332 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4333
[email protected]3c32c5f2010-05-18 15:18:124334 MockWrite data_writes1[] = {
4335 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4336 "Host: www.google.com\r\n"
4337 "Connection: keep-alive\r\n"
4338 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4339 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4340 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4341 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4342 };
4343
4344 // Sever accepts the authorization.
4345 MockRead data_reads1[] = {
4346 MockRead("HTTP/1.0 200 OK\r\n"),
4347 MockRead("Content-Length: 100\r\n\r\n"),
4348 MockRead(false, OK),
4349 };
4350
4351 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4352 data_writes1, arraysize(data_writes1));
4353 session_deps.socket_factory.AddSocketDataProvider(&data1);
4354
[email protected]f1f3f0f82011-10-01 20:38:104355 TestOldCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124356
4357 int rv = trans->Start(&request, &callback1, BoundNetLog());
4358 EXPECT_EQ(ERR_IO_PENDING, rv);
4359
4360 rv = callback1.WaitForResult();
4361 EXPECT_EQ(OK, rv);
4362
4363 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504364 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124365 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4366 }
4367}
4368
[email protected]89ceba9a2009-03-21 03:46:064369// Test the ResetStateForRestart() private method.
4370TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4371 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594372 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404373 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434374 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064375
4376 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064377 trans->read_buf_ = new IOBuffer(15);
4378 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204379 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064380
4381 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144382 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574383 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:084384 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:574385 response->response_time = base::Time::Now();
4386 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064387
4388 { // Setup state for response_.vary_data
4389 HttpRequestInfo request;
4390 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4391 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274392 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434393 request.extra_headers.SetHeader("Foo", "1");
4394 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574395 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064396 }
4397
4398 // Cause the above state to be reset.
4399 trans->ResetStateForRestart();
4400
4401 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074402 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064403 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204404 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574405 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4406 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044407 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:084408 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:574409 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064410}
4411
[email protected]bacff652009-03-31 17:50:334412// Test HTTPS connections to a site with a bad certificate
4413TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334414 HttpRequestInfo request;
4415 request.method = "GET";
4416 request.url = GURL("https://www.google.com/");
4417 request.load_flags = 0;
4418
[email protected]cb9bf6ca2011-01-28 13:15:274419 SessionDependencies session_deps;
4420 scoped_ptr<HttpTransaction> trans(
4421 new HttpNetworkTransaction(CreateSession(&session_deps)));
4422
[email protected]bacff652009-03-31 17:50:334423 MockWrite data_writes[] = {
4424 MockWrite("GET / HTTP/1.1\r\n"
4425 "Host: www.google.com\r\n"
4426 "Connection: keep-alive\r\n\r\n"),
4427 };
4428
4429 MockRead data_reads[] = {
4430 MockRead("HTTP/1.0 200 OK\r\n"),
4431 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4432 MockRead("Content-Length: 100\r\n\r\n"),
4433 MockRead(false, OK),
4434 };
4435
[email protected]5ecc992a42009-11-11 01:41:594436 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394437 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4438 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594439 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4440 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334441
[email protected]5ecc992a42009-11-11 01:41:594442 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4443 session_deps.socket_factory.AddSocketDataProvider(&data);
4444 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4445 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334446
[email protected]f1f3f0f82011-10-01 20:38:104447 TestOldCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334448
[email protected]5a1d7ca2010-04-28 20:12:274449 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334450 EXPECT_EQ(ERR_IO_PENDING, rv);
4451
4452 rv = callback.WaitForResult();
4453 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4454
4455 rv = trans->RestartIgnoringLastError(&callback);
4456 EXPECT_EQ(ERR_IO_PENDING, rv);
4457
4458 rv = callback.WaitForResult();
4459 EXPECT_EQ(OK, rv);
4460
4461 const HttpResponseInfo* response = trans->GetResponseInfo();
4462
[email protected]fe2255a2011-09-20 19:37:504463 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334464 EXPECT_EQ(100, response->headers->GetContentLength());
4465}
4466
4467// Test HTTPS connections to a site with a bad certificate, going through a
4468// proxy
4469TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004470 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334471
4472 HttpRequestInfo request;
4473 request.method = "GET";
4474 request.url = GURL("https://www.google.com/");
4475 request.load_flags = 0;
4476
4477 MockWrite proxy_writes[] = {
4478 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454479 "Host: www.google.com\r\n"
4480 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334481 };
4482
4483 MockRead proxy_reads[] = {
4484 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424485 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334486 };
4487
4488 MockWrite data_writes[] = {
4489 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454490 "Host: www.google.com\r\n"
4491 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334492 MockWrite("GET / HTTP/1.1\r\n"
4493 "Host: www.google.com\r\n"
4494 "Connection: keep-alive\r\n\r\n"),
4495 };
4496
4497 MockRead data_reads[] = {
4498 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4499 MockRead("HTTP/1.0 200 OK\r\n"),
4500 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4501 MockRead("Content-Length: 100\r\n\r\n"),
4502 MockRead(false, OK),
4503 };
4504
[email protected]31a2bfe2010-02-09 08:03:394505 StaticSocketDataProvider ssl_bad_certificate(
4506 proxy_reads, arraysize(proxy_reads),
4507 proxy_writes, arraysize(proxy_writes));
4508 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4509 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594510 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4511 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334512
[email protected]5ecc992a42009-11-11 01:41:594513 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4514 session_deps.socket_factory.AddSocketDataProvider(&data);
4515 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4516 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334517
[email protected]f1f3f0f82011-10-01 20:38:104518 TestOldCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334519
4520 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594521 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334522
[email protected]d207a5f2009-06-04 05:28:404523 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434524 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334525
[email protected]5a1d7ca2010-04-28 20:12:274526 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334527 EXPECT_EQ(ERR_IO_PENDING, rv);
4528
4529 rv = callback.WaitForResult();
4530 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4531
4532 rv = trans->RestartIgnoringLastError(&callback);
4533 EXPECT_EQ(ERR_IO_PENDING, rv);
4534
4535 rv = callback.WaitForResult();
4536 EXPECT_EQ(OK, rv);
4537
4538 const HttpResponseInfo* response = trans->GetResponseInfo();
4539
[email protected]fe2255a2011-09-20 19:37:504540 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334541 EXPECT_EQ(100, response->headers->GetContentLength());
4542 }
4543}
4544
[email protected]2df19bb2010-08-25 20:13:464545
4546// Test HTTPS connections to a site, going through an HTTPS proxy
4547TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114548 SessionDependencies session_deps(ProxyService::CreateFixed(
4549 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464550
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 MockWrite("GET / HTTP/1.1\r\n"
4561 "Host: www.google.com\r\n"
4562 "Connection: keep-alive\r\n\r\n"),
4563 };
4564
4565 MockRead data_reads[] = {
4566 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4567 MockRead("HTTP/1.1 200 OK\r\n"),
4568 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4569 MockRead("Content-Length: 100\r\n\r\n"),
4570 MockRead(false, OK),
4571 };
4572
4573 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4574 data_writes, arraysize(data_writes));
4575 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4576 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4577
4578 session_deps.socket_factory.AddSocketDataProvider(&data);
4579 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4580 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4581
[email protected]f1f3f0f82011-10-01 20:38:104582 TestOldCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464583
4584 scoped_ptr<HttpTransaction> trans(
4585 new HttpNetworkTransaction(CreateSession(&session_deps)));
4586
4587 int rv = trans->Start(&request, &callback, BoundNetLog());
4588 EXPECT_EQ(ERR_IO_PENDING, rv);
4589
4590 rv = callback.WaitForResult();
4591 EXPECT_EQ(OK, rv);
4592 const HttpResponseInfo* response = trans->GetResponseInfo();
4593
[email protected]fe2255a2011-09-20 19:37:504594 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464595
4596 EXPECT_TRUE(response->headers->IsKeepAlive());
4597 EXPECT_EQ(200, response->headers->response_code());
4598 EXPECT_EQ(100, response->headers->GetContentLength());
4599 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4600}
4601
[email protected]511f6f52010-12-17 03:58:294602// Test an HTTPS Proxy's ability to redirect a CONNECT request
4603TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4604 SessionDependencies session_deps(
4605 ProxyService::CreateFixed("https://proxy:70"));
4606
4607 HttpRequestInfo request;
4608 request.method = "GET";
4609 request.url = GURL("https://www.google.com/");
4610 request.load_flags = 0;
4611
4612 MockWrite data_writes[] = {
4613 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4614 "Host: www.google.com\r\n"
4615 "Proxy-Connection: keep-alive\r\n\r\n"),
4616 };
4617
4618 MockRead data_reads[] = {
4619 MockRead("HTTP/1.1 302 Redirect\r\n"),
4620 MockRead("Location: http://login.example.com/\r\n"),
4621 MockRead("Content-Length: 0\r\n\r\n"),
4622 MockRead(false, OK),
4623 };
4624
4625 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4626 data_writes, arraysize(data_writes));
4627 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4628
4629 session_deps.socket_factory.AddSocketDataProvider(&data);
4630 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4631
[email protected]f1f3f0f82011-10-01 20:38:104632 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294633
4634 scoped_ptr<HttpTransaction> trans(
4635 new HttpNetworkTransaction(CreateSession(&session_deps)));
4636
4637 int rv = trans->Start(&request, &callback, BoundNetLog());
4638 EXPECT_EQ(ERR_IO_PENDING, rv);
4639
4640 rv = callback.WaitForResult();
4641 EXPECT_EQ(OK, rv);
4642 const HttpResponseInfo* response = trans->GetResponseInfo();
4643
[email protected]fe2255a2011-09-20 19:37:504644 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294645
4646 EXPECT_EQ(302, response->headers->response_code());
4647 std::string url;
4648 EXPECT_TRUE(response->headers->IsRedirect(&url));
4649 EXPECT_EQ("http://login.example.com/", url);
4650}
4651
4652// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4653TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4654 SessionDependencies session_deps(
4655 ProxyService::CreateFixed("https://proxy:70"));
4656
4657 HttpRequestInfo request;
4658 request.method = "GET";
4659 request.url = GURL("https://www.google.com/");
4660 request.load_flags = 0;
4661
4662 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4663 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4664 MockWrite data_writes[] = {
4665 CreateMockWrite(*conn.get(), 0, false),
4666 };
4667
4668 static const char* const kExtraHeaders[] = {
4669 "location",
4670 "http://login.example.com/",
4671 };
4672 scoped_ptr<spdy::SpdyFrame> resp(
4673 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4674 arraysize(kExtraHeaders)/2, 1));
4675 MockRead data_reads[] = {
4676 CreateMockRead(*resp.get(), 1, false),
4677 MockRead(true, 0, 2), // EOF
4678 };
4679
4680 scoped_refptr<DelayedSocketData> data(
4681 new DelayedSocketData(
4682 1, // wait for one write to finish before reading.
4683 data_reads, arraysize(data_reads),
4684 data_writes, arraysize(data_writes)));
4685 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4686 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4687 proxy_ssl.next_proto = "spdy/2";
4688 proxy_ssl.was_npn_negotiated = true;
4689
4690 session_deps.socket_factory.AddSocketDataProvider(data.get());
4691 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4692
[email protected]f1f3f0f82011-10-01 20:38:104693 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294694
4695 scoped_ptr<HttpTransaction> trans(
4696 new HttpNetworkTransaction(CreateSession(&session_deps)));
4697
4698 int rv = trans->Start(&request, &callback, BoundNetLog());
4699 EXPECT_EQ(ERR_IO_PENDING, rv);
4700
4701 rv = callback.WaitForResult();
4702 EXPECT_EQ(OK, rv);
4703 const HttpResponseInfo* response = trans->GetResponseInfo();
4704
[email protected]fe2255a2011-09-20 19:37:504705 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294706
4707 EXPECT_EQ(302, response->headers->response_code());
4708 std::string url;
4709 EXPECT_TRUE(response->headers->IsRedirect(&url));
4710 EXPECT_EQ("http://login.example.com/", url);
4711}
4712
4713// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4714TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4715 SessionDependencies session_deps(
4716 ProxyService::CreateFixed("https://proxy:70"));
4717
4718 HttpRequestInfo request;
4719 request.method = "GET";
4720 request.url = GURL("https://www.google.com/");
4721 request.load_flags = 0;
4722
4723 MockWrite data_writes[] = {
4724 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4725 "Host: www.google.com\r\n"
4726 "Proxy-Connection: keep-alive\r\n\r\n"),
4727 };
4728
4729 MockRead data_reads[] = {
4730 MockRead("HTTP/1.1 404 Not Found\r\n"),
4731 MockRead("Content-Length: 23\r\n\r\n"),
4732 MockRead("The host does not exist"),
4733 MockRead(false, OK),
4734 };
4735
4736 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4737 data_writes, arraysize(data_writes));
4738 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4739
4740 session_deps.socket_factory.AddSocketDataProvider(&data);
4741 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4742
[email protected]f1f3f0f82011-10-01 20:38:104743 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294744
4745 scoped_ptr<HttpTransaction> trans(
4746 new HttpNetworkTransaction(CreateSession(&session_deps)));
4747
4748 int rv = trans->Start(&request, &callback, BoundNetLog());
4749 EXPECT_EQ(ERR_IO_PENDING, rv);
4750
4751 rv = callback.WaitForResult();
4752 EXPECT_EQ(OK, rv);
4753 const HttpResponseInfo* response = trans->GetResponseInfo();
4754
[email protected]fe2255a2011-09-20 19:37:504755 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294756
4757 EXPECT_EQ(404, response->headers->response_code());
4758 EXPECT_EQ(23, response->headers->GetContentLength());
4759 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4760 EXPECT_FALSE(response->ssl_info.is_valid());
4761
4762 std::string response_data;
4763 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4764 EXPECT_EQ("The host does not exist", response_data);
4765}
4766
4767// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4768// request
4769TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4770 SessionDependencies session_deps(
4771 ProxyService::CreateFixed("https://proxy:70"));
4772
4773 HttpRequestInfo request;
4774 request.method = "GET";
4775 request.url = GURL("https://www.google.com/");
4776 request.load_flags = 0;
4777
4778 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4779 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4780 MockWrite data_writes[] = {
4781 CreateMockWrite(*conn.get(), 0, false),
4782 };
4783
4784 static const char* const kExtraHeaders[] = {
4785 "location",
4786 "http://login.example.com/",
4787 };
4788 scoped_ptr<spdy::SpdyFrame> resp(
4789 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4790 arraysize(kExtraHeaders)/2, 1));
4791 scoped_ptr<spdy::SpdyFrame> body(
4792 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4793 MockRead data_reads[] = {
4794 CreateMockRead(*resp.get(), 1, false),
4795 CreateMockRead(*body.get(), 2, false),
4796 MockRead(true, 0, 3), // EOF
4797 };
4798
4799 scoped_refptr<DelayedSocketData> data(
4800 new DelayedSocketData(
4801 1, // wait for one write to finish before reading.
4802 data_reads, arraysize(data_reads),
4803 data_writes, arraysize(data_writes)));
4804 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4805 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4806 proxy_ssl.next_proto = "spdy/2";
4807 proxy_ssl.was_npn_negotiated = true;
4808
4809 session_deps.socket_factory.AddSocketDataProvider(data.get());
4810 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4811
[email protected]f1f3f0f82011-10-01 20:38:104812 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294813
4814 scoped_ptr<HttpTransaction> trans(
4815 new HttpNetworkTransaction(CreateSession(&session_deps)));
4816
4817 int rv = trans->Start(&request, &callback, BoundNetLog());
4818 EXPECT_EQ(ERR_IO_PENDING, rv);
4819
4820 rv = callback.WaitForResult();
4821 EXPECT_EQ(OK, rv);
4822 const HttpResponseInfo* response = trans->GetResponseInfo();
4823
[email protected]fe2255a2011-09-20 19:37:504824 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294825
4826 EXPECT_EQ(404, response->headers->response_code());
4827 EXPECT_FALSE(response->ssl_info.is_valid());
4828
4829 std::string response_data;
4830 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4831 EXPECT_EQ("The host does not exist", response_data);
4832}
4833
[email protected]2df19bb2010-08-25 20:13:464834// Test HTTPS connections to a site with a bad certificate, going through an
4835// HTTPS proxy
4836TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114837 SessionDependencies session_deps(ProxyService::CreateFixed(
4838 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464839
4840 HttpRequestInfo request;
4841 request.method = "GET";
4842 request.url = GURL("https://www.google.com/");
4843 request.load_flags = 0;
4844
4845 // Attempt to fetch the URL from a server with a bad cert
4846 MockWrite bad_cert_writes[] = {
4847 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4848 "Host: www.google.com\r\n"
4849 "Proxy-Connection: keep-alive\r\n\r\n"),
4850 };
4851
4852 MockRead bad_cert_reads[] = {
4853 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4854 MockRead(false, OK)
4855 };
4856
4857 // Attempt to fetch the URL with a good cert
4858 MockWrite good_data_writes[] = {
4859 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4860 "Host: www.google.com\r\n"
4861 "Proxy-Connection: keep-alive\r\n\r\n"),
4862 MockWrite("GET / HTTP/1.1\r\n"
4863 "Host: www.google.com\r\n"
4864 "Connection: keep-alive\r\n\r\n"),
4865 };
4866
4867 MockRead good_cert_reads[] = {
4868 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4869 MockRead("HTTP/1.0 200 OK\r\n"),
4870 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4871 MockRead("Content-Length: 100\r\n\r\n"),
4872 MockRead(false, OK),
4873 };
4874
4875 StaticSocketDataProvider ssl_bad_certificate(
4876 bad_cert_reads, arraysize(bad_cert_reads),
4877 bad_cert_writes, arraysize(bad_cert_writes));
4878 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4879 good_data_writes, arraysize(good_data_writes));
4880 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4881 SSLSocketDataProvider ssl(true, OK);
4882
4883 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4884 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4885 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4886 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4887
4888 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4889 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4890 session_deps.socket_factory.AddSocketDataProvider(&data);
4891 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4892
[email protected]f1f3f0f82011-10-01 20:38:104893 TestOldCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464894
4895 scoped_ptr<HttpTransaction> trans(
4896 new HttpNetworkTransaction(CreateSession(&session_deps)));
4897
4898 int rv = trans->Start(&request, &callback, BoundNetLog());
4899 EXPECT_EQ(ERR_IO_PENDING, rv);
4900
4901 rv = callback.WaitForResult();
4902 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4903
4904 rv = trans->RestartIgnoringLastError(&callback);
4905 EXPECT_EQ(ERR_IO_PENDING, rv);
4906
4907 rv = callback.WaitForResult();
4908 EXPECT_EQ(OK, rv);
4909
4910 const HttpResponseInfo* response = trans->GetResponseInfo();
4911
[email protected]fe2255a2011-09-20 19:37:504912 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464913 EXPECT_EQ(100, response->headers->GetContentLength());
4914}
4915
[email protected]1c773ea12009-04-28 19:58:424916TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424917 HttpRequestInfo request;
4918 request.method = "GET";
4919 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434920 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4921 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424922
[email protected]cb9bf6ca2011-01-28 13:15:274923 SessionDependencies session_deps;
4924 scoped_ptr<HttpTransaction> trans(
4925 new HttpNetworkTransaction(CreateSession(&session_deps)));
4926
[email protected]1c773ea12009-04-28 19:58:424927 MockWrite data_writes[] = {
4928 MockWrite("GET / HTTP/1.1\r\n"
4929 "Host: www.google.com\r\n"
4930 "Connection: keep-alive\r\n"
4931 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4932 };
4933
4934 // Lastly, the server responds with the actual content.
4935 MockRead data_reads[] = {
4936 MockRead("HTTP/1.0 200 OK\r\n"),
4937 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4938 MockRead("Content-Length: 100\r\n\r\n"),
4939 MockRead(false, OK),
4940 };
4941
[email protected]31a2bfe2010-02-09 08:03:394942 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4943 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594944 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424945
[email protected]f1f3f0f82011-10-01 20:38:104946 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424947
[email protected]5a1d7ca2010-04-28 20:12:274948 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424949 EXPECT_EQ(ERR_IO_PENDING, rv);
4950
4951 rv = callback.WaitForResult();
4952 EXPECT_EQ(OK, rv);
4953}
4954
[email protected]da81f132010-08-18 23:39:294955TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294956 HttpRequestInfo request;
4957 request.method = "GET";
4958 request.url = GURL("https://www.google.com/");
4959 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4960 "Chromium Ultra Awesome X Edition");
4961
[email protected]cb9bf6ca2011-01-28 13:15:274962 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4963 scoped_ptr<HttpTransaction> trans(
4964 new HttpNetworkTransaction(CreateSession(&session_deps)));
4965
[email protected]da81f132010-08-18 23:39:294966 MockWrite data_writes[] = {
4967 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4968 "Host: www.google.com\r\n"
4969 "Proxy-Connection: keep-alive\r\n"
4970 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4971 };
4972 MockRead data_reads[] = {
4973 // Return an error, so the transaction stops here (this test isn't
4974 // interested in the rest).
4975 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4976 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4977 MockRead("Proxy-Connection: close\r\n\r\n"),
4978 };
4979
4980 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4981 data_writes, arraysize(data_writes));
4982 session_deps.socket_factory.AddSocketDataProvider(&data);
4983
[email protected]f1f3f0f82011-10-01 20:38:104984 TestOldCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:294985
4986 int rv = trans->Start(&request, &callback, BoundNetLog());
4987 EXPECT_EQ(ERR_IO_PENDING, rv);
4988
4989 rv = callback.WaitForResult();
4990 EXPECT_EQ(OK, rv);
4991}
4992
[email protected]1c773ea12009-04-28 19:58:424993TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424994 HttpRequestInfo request;
4995 request.method = "GET";
4996 request.url = GURL("http://www.google.com/");
4997 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:164998 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
4999 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:425000
[email protected]cb9bf6ca2011-01-28 13:15:275001 SessionDependencies session_deps;
5002 scoped_ptr<HttpTransaction> trans(
5003 new HttpNetworkTransaction(CreateSession(&session_deps)));
5004
[email protected]1c773ea12009-04-28 19:58:425005 MockWrite data_writes[] = {
5006 MockWrite("GET / HTTP/1.1\r\n"
5007 "Host: www.google.com\r\n"
5008 "Connection: keep-alive\r\n"
5009 "Referer: http://the.previous.site.com/\r\n\r\n"),
5010 };
5011
5012 // Lastly, the server responds with the actual content.
5013 MockRead data_reads[] = {
5014 MockRead("HTTP/1.0 200 OK\r\n"),
5015 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5016 MockRead("Content-Length: 100\r\n\r\n"),
5017 MockRead(false, OK),
5018 };
5019
[email protected]31a2bfe2010-02-09 08:03:395020 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5021 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595022 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425023
[email protected]f1f3f0f82011-10-01 20:38:105024 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425025
[email protected]5a1d7ca2010-04-28 20:12:275026 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425027 EXPECT_EQ(ERR_IO_PENDING, rv);
5028
5029 rv = callback.WaitForResult();
5030 EXPECT_EQ(OK, rv);
5031}
5032
5033TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425034 HttpRequestInfo request;
5035 request.method = "POST";
5036 request.url = GURL("http://www.google.com/");
5037
[email protected]cb9bf6ca2011-01-28 13:15:275038 SessionDependencies session_deps;
5039 scoped_ptr<HttpTransaction> trans(
5040 new HttpNetworkTransaction(CreateSession(&session_deps)));
5041
[email protected]1c773ea12009-04-28 19:58:425042 MockWrite data_writes[] = {
5043 MockWrite("POST / HTTP/1.1\r\n"
5044 "Host: www.google.com\r\n"
5045 "Connection: keep-alive\r\n"
5046 "Content-Length: 0\r\n\r\n"),
5047 };
5048
5049 // Lastly, the server responds with the actual content.
5050 MockRead data_reads[] = {
5051 MockRead("HTTP/1.0 200 OK\r\n"),
5052 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5053 MockRead("Content-Length: 100\r\n\r\n"),
5054 MockRead(false, OK),
5055 };
5056
[email protected]31a2bfe2010-02-09 08:03:395057 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5058 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595059 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425060
[email protected]f1f3f0f82011-10-01 20:38:105061 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425062
[email protected]5a1d7ca2010-04-28 20:12:275063 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425064 EXPECT_EQ(ERR_IO_PENDING, rv);
5065
5066 rv = callback.WaitForResult();
5067 EXPECT_EQ(OK, rv);
5068}
5069
5070TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425071 HttpRequestInfo request;
5072 request.method = "PUT";
5073 request.url = GURL("http://www.google.com/");
5074
[email protected]cb9bf6ca2011-01-28 13:15:275075 SessionDependencies session_deps;
5076 scoped_ptr<HttpTransaction> trans(
5077 new HttpNetworkTransaction(CreateSession(&session_deps)));
5078
[email protected]1c773ea12009-04-28 19:58:425079 MockWrite data_writes[] = {
5080 MockWrite("PUT / HTTP/1.1\r\n"
5081 "Host: www.google.com\r\n"
5082 "Connection: keep-alive\r\n"
5083 "Content-Length: 0\r\n\r\n"),
5084 };
5085
5086 // Lastly, the server responds with the actual content.
5087 MockRead data_reads[] = {
5088 MockRead("HTTP/1.0 200 OK\r\n"),
5089 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5090 MockRead("Content-Length: 100\r\n\r\n"),
5091 MockRead(false, OK),
5092 };
5093
[email protected]31a2bfe2010-02-09 08:03:395094 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5095 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595096 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425097
[email protected]f1f3f0f82011-10-01 20:38:105098 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425099
[email protected]5a1d7ca2010-04-28 20:12:275100 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425101 EXPECT_EQ(ERR_IO_PENDING, rv);
5102
5103 rv = callback.WaitForResult();
5104 EXPECT_EQ(OK, rv);
5105}
5106
5107TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425108 HttpRequestInfo request;
5109 request.method = "HEAD";
5110 request.url = GURL("http://www.google.com/");
5111
[email protected]cb9bf6ca2011-01-28 13:15:275112 SessionDependencies session_deps;
5113 scoped_ptr<HttpTransaction> trans(
5114 new HttpNetworkTransaction(CreateSession(&session_deps)));
5115
[email protected]1c773ea12009-04-28 19:58:425116 MockWrite data_writes[] = {
5117 MockWrite("HEAD / HTTP/1.1\r\n"
5118 "Host: www.google.com\r\n"
5119 "Connection: keep-alive\r\n"
5120 "Content-Length: 0\r\n\r\n"),
5121 };
5122
5123 // Lastly, the server responds with the actual content.
5124 MockRead data_reads[] = {
5125 MockRead("HTTP/1.0 200 OK\r\n"),
5126 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5127 MockRead("Content-Length: 100\r\n\r\n"),
5128 MockRead(false, OK),
5129 };
5130
[email protected]31a2bfe2010-02-09 08:03:395131 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5132 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595133 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425134
[email protected]f1f3f0f82011-10-01 20:38:105135 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425136
[email protected]5a1d7ca2010-04-28 20:12:275137 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425138 EXPECT_EQ(ERR_IO_PENDING, rv);
5139
5140 rv = callback.WaitForResult();
5141 EXPECT_EQ(OK, rv);
5142}
5143
5144TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425145 HttpRequestInfo request;
5146 request.method = "GET";
5147 request.url = GURL("http://www.google.com/");
5148 request.load_flags = LOAD_BYPASS_CACHE;
5149
[email protected]cb9bf6ca2011-01-28 13:15:275150 SessionDependencies session_deps;
5151 scoped_ptr<HttpTransaction> trans(
5152 new HttpNetworkTransaction(CreateSession(&session_deps)));
5153
[email protected]1c773ea12009-04-28 19:58:425154 MockWrite data_writes[] = {
5155 MockWrite("GET / HTTP/1.1\r\n"
5156 "Host: www.google.com\r\n"
5157 "Connection: keep-alive\r\n"
5158 "Pragma: no-cache\r\n"
5159 "Cache-Control: no-cache\r\n\r\n"),
5160 };
5161
5162 // Lastly, the server responds with the actual content.
5163 MockRead data_reads[] = {
5164 MockRead("HTTP/1.0 200 OK\r\n"),
5165 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5166 MockRead("Content-Length: 100\r\n\r\n"),
5167 MockRead(false, OK),
5168 };
5169
[email protected]31a2bfe2010-02-09 08:03:395170 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5171 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595172 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425173
[email protected]f1f3f0f82011-10-01 20:38:105174 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425175
[email protected]5a1d7ca2010-04-28 20:12:275176 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425177 EXPECT_EQ(ERR_IO_PENDING, rv);
5178
5179 rv = callback.WaitForResult();
5180 EXPECT_EQ(OK, rv);
5181}
5182
5183TEST_F(HttpNetworkTransactionTest,
5184 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425185 HttpRequestInfo request;
5186 request.method = "GET";
5187 request.url = GURL("http://www.google.com/");
5188 request.load_flags = LOAD_VALIDATE_CACHE;
5189
[email protected]cb9bf6ca2011-01-28 13:15:275190 SessionDependencies session_deps;
5191 scoped_ptr<HttpTransaction> trans(
5192 new HttpNetworkTransaction(CreateSession(&session_deps)));
5193
[email protected]1c773ea12009-04-28 19:58:425194 MockWrite data_writes[] = {
5195 MockWrite("GET / HTTP/1.1\r\n"
5196 "Host: www.google.com\r\n"
5197 "Connection: keep-alive\r\n"
5198 "Cache-Control: max-age=0\r\n\r\n"),
5199 };
5200
5201 // Lastly, the server responds with the actual content.
5202 MockRead data_reads[] = {
5203 MockRead("HTTP/1.0 200 OK\r\n"),
5204 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5205 MockRead("Content-Length: 100\r\n\r\n"),
5206 MockRead(false, OK),
5207 };
5208
[email protected]31a2bfe2010-02-09 08:03:395209 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5210 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595211 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425212
[email protected]f1f3f0f82011-10-01 20:38:105213 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425214
[email protected]5a1d7ca2010-04-28 20:12:275215 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425216 EXPECT_EQ(ERR_IO_PENDING, rv);
5217
5218 rv = callback.WaitForResult();
5219 EXPECT_EQ(OK, rv);
5220}
5221
5222TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425223 HttpRequestInfo request;
5224 request.method = "GET";
5225 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435226 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425227
[email protected]cb9bf6ca2011-01-28 13:15:275228 SessionDependencies session_deps;
5229 scoped_ptr<HttpTransaction> trans(
5230 new HttpNetworkTransaction(CreateSession(&session_deps)));
5231
[email protected]1c773ea12009-04-28 19:58:425232 MockWrite data_writes[] = {
5233 MockWrite("GET / HTTP/1.1\r\n"
5234 "Host: www.google.com\r\n"
5235 "Connection: keep-alive\r\n"
5236 "FooHeader: Bar\r\n\r\n"),
5237 };
5238
5239 // Lastly, the server responds with the actual content.
5240 MockRead data_reads[] = {
5241 MockRead("HTTP/1.0 200 OK\r\n"),
5242 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5243 MockRead("Content-Length: 100\r\n\r\n"),
5244 MockRead(false, OK),
5245 };
5246
[email protected]31a2bfe2010-02-09 08:03:395247 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5248 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595249 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425250
[email protected]f1f3f0f82011-10-01 20:38:105251 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425252
[email protected]5a1d7ca2010-04-28 20:12:275253 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425254 EXPECT_EQ(ERR_IO_PENDING, rv);
5255
5256 rv = callback.WaitForResult();
5257 EXPECT_EQ(OK, rv);
5258}
5259
[email protected]270c6412010-03-29 22:02:475260TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475261 HttpRequestInfo request;
5262 request.method = "GET";
5263 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435264 request.extra_headers.SetHeader("referer", "www.foo.com");
5265 request.extra_headers.SetHeader("hEllo", "Kitty");
5266 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475267
[email protected]cb9bf6ca2011-01-28 13:15:275268 SessionDependencies session_deps;
5269 scoped_ptr<HttpTransaction> trans(
5270 new HttpNetworkTransaction(CreateSession(&session_deps)));
5271
[email protected]270c6412010-03-29 22:02:475272 MockWrite data_writes[] = {
5273 MockWrite("GET / HTTP/1.1\r\n"
5274 "Host: www.google.com\r\n"
5275 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165276 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475277 "hEllo: Kitty\r\n"
5278 "FoO: bar\r\n\r\n"),
5279 };
5280
5281 // Lastly, the server responds with the actual content.
5282 MockRead data_reads[] = {
5283 MockRead("HTTP/1.0 200 OK\r\n"),
5284 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5285 MockRead("Content-Length: 100\r\n\r\n"),
5286 MockRead(false, OK),
5287 };
5288
5289 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5290 data_writes, arraysize(data_writes));
5291 session_deps.socket_factory.AddSocketDataProvider(&data);
5292
[email protected]f1f3f0f82011-10-01 20:38:105293 TestOldCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:475294
[email protected]5a1d7ca2010-04-28 20:12:275295 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475296 EXPECT_EQ(ERR_IO_PENDING, rv);
5297
5298 rv = callback.WaitForResult();
5299 EXPECT_EQ(OK, rv);
5300}
5301
[email protected]3cd17242009-06-23 02:59:025302TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275303 HttpRequestInfo request;
5304 request.method = "GET";
5305 request.url = GURL("http://www.google.com/");
5306 request.load_flags = 0;
5307
[email protected]80d6524d2009-08-18 03:58:095308 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005309 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025310
5311 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435312 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025313
[email protected]3cd17242009-06-23 02:59:025314 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5315 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5316
5317 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355318 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025319 MockWrite("GET / HTTP/1.1\r\n"
5320 "Host: www.google.com\r\n"
5321 "Connection: keep-alive\r\n\r\n")
5322 };
5323
5324 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595325 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025326 MockRead("HTTP/1.0 200 OK\r\n"),
5327 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5328 MockRead("Payload"),
5329 MockRead(false, OK)
5330 };
5331
[email protected]31a2bfe2010-02-09 08:03:395332 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5333 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595334 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025335
[email protected]f1f3f0f82011-10-01 20:38:105336 TestOldCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025337
[email protected]5a1d7ca2010-04-28 20:12:275338 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025339 EXPECT_EQ(ERR_IO_PENDING, rv);
5340
5341 rv = callback.WaitForResult();
5342 EXPECT_EQ(OK, rv);
5343
5344 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505345 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025346
5347 std::string response_text;
5348 rv = ReadTransaction(trans.get(), &response_text);
5349 EXPECT_EQ(OK, rv);
5350 EXPECT_EQ("Payload", response_text);
5351}
5352
5353TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275354 HttpRequestInfo request;
5355 request.method = "GET";
5356 request.url = GURL("https://www.google.com/");
5357 request.load_flags = 0;
5358
[email protected]80d6524d2009-08-18 03:58:095359 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005360 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025361
5362 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435363 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025364
[email protected]3cd17242009-06-23 02:59:025365 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5366 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5367
5368 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355369 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5370 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025371 MockWrite("GET / HTTP/1.1\r\n"
5372 "Host: www.google.com\r\n"
5373 "Connection: keep-alive\r\n\r\n")
5374 };
5375
5376 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355377 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5378 arraysize(read_buffer)),
5379 MockRead("HTTP/1.0 200 OK\r\n"),
5380 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5381 MockRead("Payload"),
5382 MockRead(false, OK)
5383 };
5384
[email protected]31a2bfe2010-02-09 08:03:395385 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5386 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595387 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355388
[email protected]5ecc992a42009-11-11 01:41:595389 SSLSocketDataProvider ssl(true, OK);
5390 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355391
[email protected]f1f3f0f82011-10-01 20:38:105392 TestOldCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355393
[email protected]5a1d7ca2010-04-28 20:12:275394 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355395 EXPECT_EQ(ERR_IO_PENDING, rv);
5396
5397 rv = callback.WaitForResult();
5398 EXPECT_EQ(OK, rv);
5399
5400 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505401 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355402
5403 std::string response_text;
5404 rv = ReadTransaction(trans.get(), &response_text);
5405 EXPECT_EQ(OK, rv);
5406 EXPECT_EQ("Payload", response_text);
5407}
5408
5409TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275410 HttpRequestInfo request;
5411 request.method = "GET";
5412 request.url = GURL("http://www.google.com/");
5413 request.load_flags = 0;
5414
[email protected]80d6524d2009-08-18 03:58:095415 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005416 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355417
5418 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435419 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355420
[email protected]e0c27be2009-07-15 13:09:355421 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5422 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375423 const char kSOCKS5OkRequest[] = {
5424 0x05, // Version
5425 0x01, // Command (CONNECT)
5426 0x00, // Reserved.
5427 0x03, // Address type (DOMAINNAME).
5428 0x0E, // Length of domain (14)
5429 // Domain string:
5430 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5431 0x00, 0x50, // 16-bit port (80)
5432 };
[email protected]e0c27be2009-07-15 13:09:355433 const char kSOCKS5OkResponse[] =
5434 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5435
5436 MockWrite data_writes[] = {
5437 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5438 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5439 MockWrite("GET / HTTP/1.1\r\n"
5440 "Host: www.google.com\r\n"
5441 "Connection: keep-alive\r\n\r\n")
5442 };
5443
5444 MockRead data_reads[] = {
5445 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5446 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5447 MockRead("HTTP/1.0 200 OK\r\n"),
5448 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5449 MockRead("Payload"),
5450 MockRead(false, OK)
5451 };
5452
[email protected]31a2bfe2010-02-09 08:03:395453 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5454 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595455 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355456
[email protected]f1f3f0f82011-10-01 20:38:105457 TestOldCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355458
[email protected]5a1d7ca2010-04-28 20:12:275459 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355460 EXPECT_EQ(ERR_IO_PENDING, rv);
5461
5462 rv = callback.WaitForResult();
5463 EXPECT_EQ(OK, rv);
5464
5465 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505466 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355467
5468 std::string response_text;
5469 rv = ReadTransaction(trans.get(), &response_text);
5470 EXPECT_EQ(OK, rv);
5471 EXPECT_EQ("Payload", response_text);
5472}
5473
5474TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275475 HttpRequestInfo request;
5476 request.method = "GET";
5477 request.url = GURL("https://www.google.com/");
5478 request.load_flags = 0;
5479
[email protected]80d6524d2009-08-18 03:58:095480 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005481 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355482
5483 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435484 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355485
[email protected]e0c27be2009-07-15 13:09:355486 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5487 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375488 const unsigned char kSOCKS5OkRequest[] = {
5489 0x05, // Version
5490 0x01, // Command (CONNECT)
5491 0x00, // Reserved.
5492 0x03, // Address type (DOMAINNAME).
5493 0x0E, // Length of domain (14)
5494 // Domain string:
5495 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5496 0x01, 0xBB, // 16-bit port (443)
5497 };
5498
[email protected]e0c27be2009-07-15 13:09:355499 const char kSOCKS5OkResponse[] =
5500 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5501
5502 MockWrite data_writes[] = {
5503 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5504 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5505 arraysize(kSOCKS5OkRequest)),
5506 MockWrite("GET / HTTP/1.1\r\n"
5507 "Host: www.google.com\r\n"
5508 "Connection: keep-alive\r\n\r\n")
5509 };
5510
5511 MockRead data_reads[] = {
5512 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5513 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025514 MockRead("HTTP/1.0 200 OK\r\n"),
5515 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5516 MockRead("Payload"),
5517 MockRead(false, OK)
5518 };
5519
[email protected]31a2bfe2010-02-09 08:03:395520 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5521 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595522 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025523
[email protected]5ecc992a42009-11-11 01:41:595524 SSLSocketDataProvider ssl(true, OK);
5525 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025526
[email protected]f1f3f0f82011-10-01 20:38:105527 TestOldCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025528
[email protected]5a1d7ca2010-04-28 20:12:275529 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025530 EXPECT_EQ(ERR_IO_PENDING, rv);
5531
5532 rv = callback.WaitForResult();
5533 EXPECT_EQ(OK, rv);
5534
5535 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505536 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025537
5538 std::string response_text;
5539 rv = ReadTransaction(trans.get(), &response_text);
5540 EXPECT_EQ(OK, rv);
5541 EXPECT_EQ("Payload", response_text);
5542}
5543
[email protected]04e5be32009-06-26 20:00:315544// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065545
5546struct GroupNameTest {
5547 std::string proxy_server;
5548 std::string url;
5549 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185550 bool ssl;
[email protected]2d731a32010-04-29 01:04:065551};
5552
5553scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025554 SessionDependencies* session_deps) {
5555 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065556
[email protected]17291a022011-10-10 07:32:535557 HttpServerProperties* http_server_properties =
5558 session->http_server_properties();
5559 http_server_properties->SetAlternateProtocol(
[email protected]2d731a32010-04-29 01:04:065560 HostPortPair("host.with.alternate", 80), 443,
[email protected]17291a022011-10-10 07:32:535561 NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065562
5563 return session;
5564}
5565
5566int GroupNameTransactionHelper(
5567 const std::string& url,
5568 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065569 HttpRequestInfo request;
5570 request.method = "GET";
5571 request.url = GURL(url);
5572 request.load_flags = 0;
5573
[email protected]cb9bf6ca2011-01-28 13:15:275574 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5575
[email protected]f1f3f0f82011-10-01 20:38:105576 TestOldCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:065577
5578 // We do not complete this request, the dtor will clean the transaction up.
5579 return trans->Start(&request, &callback, BoundNetLog());
5580}
5581
5582TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5583 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315584 {
[email protected]2d731a32010-04-29 01:04:065585 "", // unused
[email protected]04e5be32009-06-26 20:00:315586 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545587 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185588 false,
[email protected]2ff8b312010-04-26 22:20:545589 },
5590 {
[email protected]2d731a32010-04-29 01:04:065591 "", // unused
[email protected]2ff8b312010-04-26 22:20:545592 "http://[2001:1418:13:1::25]/direct",
5593 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185594 false,
[email protected]04e5be32009-06-26 20:00:315595 },
[email protected]04e5be32009-06-26 20:00:315596
5597 // SSL Tests
5598 {
[email protected]2d731a32010-04-29 01:04:065599 "", // unused
[email protected]04e5be32009-06-26 20:00:315600 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025601 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185602 true,
[email protected]04e5be32009-06-26 20:00:315603 },
5604 {
[email protected]2d731a32010-04-29 01:04:065605 "", // unused
5606 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025607 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185608 true,
[email protected]04e5be32009-06-26 20:00:315609 },
5610 {
[email protected]2d731a32010-04-29 01:04:065611 "", // unused
[email protected]2ff8b312010-04-26 22:20:545612 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025613 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185614 true,
[email protected]2ff8b312010-04-26 22:20:545615 },
[email protected]2d731a32010-04-29 01:04:065616 };
[email protected]2ff8b312010-04-26 22:20:545617
[email protected]8e6441ca2010-08-19 05:56:385618 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065619
5620 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025621 SessionDependencies session_deps(
5622 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065623 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025624 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065625
5626 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285627 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5628 new CaptureGroupNameTransportSocketPool(NULL, NULL);
5629 peer.SetTransportSocketPool(transport_conn_pool);
[email protected]2431756e2010-09-29 20:26:135630 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345631 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185632 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065633
5634 EXPECT_EQ(ERR_IO_PENDING,
5635 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185636 if (tests[i].ssl)
5637 EXPECT_EQ(tests[i].expected_group_name,
5638 ssl_conn_pool->last_group_name_received());
5639 else
5640 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285641 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065642 }
5643
[email protected]8e6441ca2010-08-19 05:56:385644 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065645}
5646
5647TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5648 const GroupNameTest tests[] = {
5649 {
5650 "http_proxy",
5651 "http://www.google.com/http_proxy_normal",
5652 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185653 false,
[email protected]2d731a32010-04-29 01:04:065654 },
5655
5656 // SSL Tests
5657 {
5658 "http_proxy",
5659 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025660 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185661 true,
[email protected]2d731a32010-04-29 01:04:065662 },
[email protected]af3490e2010-10-16 21:02:295663
[email protected]9faeded92010-04-29 20:03:055664 {
5665 "http_proxy",
5666 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025667 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185668 true,
[email protected]9faeded92010-04-29 20:03:055669 },
[email protected]2d731a32010-04-29 01:04:065670 };
5671
[email protected]8e6441ca2010-08-19 05:56:385672 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065673
5674 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025675 SessionDependencies session_deps(
5676 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065677 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025678 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065679
5680 HttpNetworkSessionPeer peer(session);
5681
[email protected]e60e47a2010-07-14 03:37:185682 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135683 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345684 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185685 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135686 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345687 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185688 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065689
5690 EXPECT_EQ(ERR_IO_PENDING,
5691 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185692 if (tests[i].ssl)
5693 EXPECT_EQ(tests[i].expected_group_name,
5694 ssl_conn_pool->last_group_name_received());
5695 else
5696 EXPECT_EQ(tests[i].expected_group_name,
5697 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065698 }
5699
[email protected]8e6441ca2010-08-19 05:56:385700 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065701}
5702
5703TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5704 const GroupNameTest tests[] = {
5705 {
5706 "socks4://socks_proxy:1080",
5707 "http://www.google.com/socks4_direct",
5708 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185709 false,
[email protected]2d731a32010-04-29 01:04:065710 },
5711 {
5712 "socks5://socks_proxy:1080",
5713 "http://www.google.com/socks5_direct",
5714 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185715 false,
[email protected]2d731a32010-04-29 01:04:065716 },
5717
5718 // SSL Tests
5719 {
5720 "socks4://socks_proxy:1080",
5721 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025722 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185723 true,
[email protected]2d731a32010-04-29 01:04:065724 },
5725 {
5726 "socks5://socks_proxy:1080",
5727 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025728 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185729 true,
[email protected]2d731a32010-04-29 01:04:065730 },
[email protected]af3490e2010-10-16 21:02:295731
[email protected]9faeded92010-04-29 20:03:055732 {
5733 "socks4://socks_proxy:1080",
5734 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025735 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185736 true,
[email protected]9faeded92010-04-29 20:03:055737 },
[email protected]04e5be32009-06-26 20:00:315738 };
5739
[email protected]8e6441ca2010-08-19 05:56:385740 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545741
[email protected]04e5be32009-06-26 20:00:315742 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025743 SessionDependencies session_deps(
5744 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065745 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025746 SetupSessionForGroupNameTests(&session_deps));
5747
[email protected]2d731a32010-04-29 01:04:065748 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315749
[email protected]e60e47a2010-07-14 03:37:185750 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135751 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345752 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185753 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135754 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345755 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185756 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315757
[email protected]5695b8c2009-09-30 21:36:435758 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315759
[email protected]2d731a32010-04-29 01:04:065760 EXPECT_EQ(ERR_IO_PENDING,
5761 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185762 if (tests[i].ssl)
5763 EXPECT_EQ(tests[i].expected_group_name,
5764 ssl_conn_pool->last_group_name_received());
5765 else
5766 EXPECT_EQ(tests[i].expected_group_name,
5767 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315768 }
[email protected]2ff8b312010-04-26 22:20:545769
[email protected]8e6441ca2010-08-19 05:56:385770 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315771}
5772
[email protected]9172a982009-06-06 00:30:255773TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275774 HttpRequestInfo request;
5775 request.method = "GET";
5776 request.url = GURL("http://www.google.com/");
5777
[email protected]5c6a17e2009-06-10 00:54:545778 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005779 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325780
[email protected]69719062010-01-05 20:09:215781 // This simulates failure resolving all hostnames; that means we will fail
5782 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325783 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5784
[email protected]9172a982009-06-06 00:30:255785 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435786 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255787
[email protected]f1f3f0f82011-10-01 20:38:105788 TestOldCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:255789
[email protected]5a1d7ca2010-04-28 20:12:275790 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255791 EXPECT_EQ(ERR_IO_PENDING, rv);
5792
[email protected]9172a982009-06-06 00:30:255793 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015794 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255795}
5796
[email protected]685af592010-05-11 19:31:245797// Base test to make sure that when the load flags for a request specify to
5798// bypass the cache, the DNS cache is not used.
5799void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275800 // Issue a request, asking to bypass the cache(s).
5801 HttpRequestInfo request;
5802 request.method = "GET";
5803 request.load_flags = load_flags;
5804 request.url = GURL("http://www.google.com/");
5805
[email protected]3b9cca42009-06-16 01:08:285806 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325807
[email protected]a2c2fb92009-07-18 07:31:045808 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545809 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325810
[email protected]3b9cca42009-06-16 01:08:285811 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435812 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285813
[email protected]6e78dfb2011-07-28 21:34:475814 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285815 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:295816 TestCompletionCallback callback;
5817 TestOldCompletionCallback old_callback;
[email protected]94a0d3d92009-06-27 01:50:145818 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105819 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295820 callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:475821 EXPECT_EQ(ERR_IO_PENDING, rv);
5822 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285823 EXPECT_EQ(OK, rv);
5824
5825 // Verify that it was added to host cache, by doing a subsequent async lookup
5826 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465827 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105828 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295829 callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325830 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285831
5832 // Inject a failure the next time that "www.google.com" is resolved. This way
5833 // we can tell if the next lookup hit the cache, or the "network".
5834 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325835 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285836
5837 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5838 // first read -- this won't be reached as the host resolution will fail first.
5839 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395840 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595841 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285842
[email protected]3b9cca42009-06-16 01:08:285843 // Run the request.
[email protected]aa22b242011-11-16 18:58:295844 rv = trans->Start(&request, &old_callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285845 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]aa22b242011-11-16 18:58:295846 rv = old_callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285847
5848 // If we bypassed the cache, we would have gotten a failure while resolving
5849 // "www.google.com".
5850 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5851}
5852
[email protected]685af592010-05-11 19:31:245853// There are multiple load flags that should trigger the host cache bypass.
5854// Test each in isolation:
5855TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5856 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5857}
5858
5859TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5860 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5861}
5862
5863TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5864 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5865}
5866
[email protected]0877e3d2009-10-17 22:29:575867// Make sure we can handle an error when writing the request.
5868TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5869 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275870 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575871
5872 HttpRequestInfo request;
5873 request.method = "GET";
5874 request.url = GURL("http://www.foo.com/");
5875 request.load_flags = 0;
5876
5877 MockWrite write_failure[] = {
5878 MockWrite(true, ERR_CONNECTION_RESET),
5879 };
[email protected]31a2bfe2010-02-09 08:03:395880 StaticSocketDataProvider data(NULL, 0,
5881 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595882 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575883
[email protected]f1f3f0f82011-10-01 20:38:105884 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575885
5886 scoped_ptr<HttpTransaction> trans(
5887 new HttpNetworkTransaction(CreateSession(&session_deps)));
5888
[email protected]5a1d7ca2010-04-28 20:12:275889 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575890 EXPECT_EQ(ERR_IO_PENDING, rv);
5891
5892 rv = callback.WaitForResult();
5893 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5894}
5895
5896// Check that a connection closed after the start of the headers finishes ok.
5897TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5898 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275899 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575900
5901 HttpRequestInfo request;
5902 request.method = "GET";
5903 request.url = GURL("http://www.foo.com/");
5904 request.load_flags = 0;
5905
5906 MockRead data_reads[] = {
5907 MockRead("HTTP/1."),
5908 MockRead(false, OK),
5909 };
5910
[email protected]31a2bfe2010-02-09 08:03:395911 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595912 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575913
[email protected]f1f3f0f82011-10-01 20:38:105914 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575915
5916 scoped_ptr<HttpTransaction> trans(
5917 new HttpNetworkTransaction(CreateSession(&session_deps)));
5918
[email protected]5a1d7ca2010-04-28 20:12:275919 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575920 EXPECT_EQ(ERR_IO_PENDING, rv);
5921
5922 rv = callback.WaitForResult();
5923 EXPECT_EQ(OK, rv);
5924
5925 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505926 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:575927
5928 EXPECT_TRUE(response->headers != NULL);
5929 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5930
5931 std::string response_data;
5932 rv = ReadTransaction(trans.get(), &response_data);
5933 EXPECT_EQ(OK, rv);
5934 EXPECT_EQ("", response_data);
5935}
5936
5937// Make sure that a dropped connection while draining the body for auth
5938// restart does the right thing.
5939TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5940 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275941 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575942
5943 HttpRequestInfo request;
5944 request.method = "GET";
5945 request.url = GURL("http://www.google.com/");
5946 request.load_flags = 0;
5947
5948 MockWrite data_writes1[] = {
5949 MockWrite("GET / HTTP/1.1\r\n"
5950 "Host: www.google.com\r\n"
5951 "Connection: keep-alive\r\n\r\n"),
5952 };
5953
5954 MockRead data_reads1[] = {
5955 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5956 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5957 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5958 MockRead("Content-Length: 14\r\n\r\n"),
5959 MockRead("Unauth"),
5960 MockRead(true, ERR_CONNECTION_RESET),
5961 };
5962
[email protected]31a2bfe2010-02-09 08:03:395963 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5964 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595965 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575966
5967 // After calling trans->RestartWithAuth(), this is the request we should
5968 // be issuing -- the final header line contains the credentials.
5969 MockWrite data_writes2[] = {
5970 MockWrite("GET / HTTP/1.1\r\n"
5971 "Host: www.google.com\r\n"
5972 "Connection: keep-alive\r\n"
5973 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5974 };
5975
5976 // Lastly, the server responds with the actual content.
5977 MockRead data_reads2[] = {
5978 MockRead("HTTP/1.1 200 OK\r\n"),
5979 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5980 MockRead("Content-Length: 100\r\n\r\n"),
5981 MockRead(false, OK),
5982 };
5983
[email protected]31a2bfe2010-02-09 08:03:395984 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5985 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595986 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575987
[email protected]f1f3f0f82011-10-01 20:38:105988 TestOldCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:575989
[email protected]0b0bf032010-09-21 18:08:505990 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5991
[email protected]5a1d7ca2010-04-28 20:12:275992 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575993 EXPECT_EQ(ERR_IO_PENDING, rv);
5994
5995 rv = callback1.WaitForResult();
5996 EXPECT_EQ(OK, rv);
5997
5998 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505999 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046000 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:576001
[email protected]f1f3f0f82011-10-01 20:38:106002 TestOldCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:576003
[email protected]f3cf9802011-10-28 18:44:586004 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]0877e3d2009-10-17 22:29:576005 EXPECT_EQ(ERR_IO_PENDING, rv);
6006
6007 rv = callback2.WaitForResult();
6008 EXPECT_EQ(OK, rv);
6009
6010 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506011 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:576012 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6013 EXPECT_EQ(100, response->headers->GetContentLength());
6014}
6015
6016// Test HTTPS connections going through a proxy that sends extra data.
6017TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006018 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576019
6020 HttpRequestInfo request;
6021 request.method = "GET";
6022 request.url = GURL("https://www.google.com/");
6023 request.load_flags = 0;
6024
6025 MockRead proxy_reads[] = {
6026 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6027 MockRead(false, OK)
6028 };
6029
[email protected]31a2bfe2010-02-09 08:03:396030 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596031 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576032
[email protected]5ecc992a42009-11-11 01:41:596033 session_deps.socket_factory.AddSocketDataProvider(&data);
6034 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576035
[email protected]f1f3f0f82011-10-01 20:38:106036 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:576037
6038 session_deps.socket_factory.ResetNextMockIndexes();
6039
6040 scoped_ptr<HttpTransaction> trans(
6041 new HttpNetworkTransaction(CreateSession(&session_deps)));
6042
[email protected]5a1d7ca2010-04-28 20:12:276043 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576044 EXPECT_EQ(ERR_IO_PENDING, rv);
6045
6046 rv = callback.WaitForResult();
6047 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6048}
6049
[email protected]e22e1362009-11-23 21:31:126050TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466051 HttpRequestInfo request;
6052 request.method = "GET";
6053 request.url = GURL("http://www.google.com/");
6054 request.load_flags = 0;
6055
[email protected]cb9bf6ca2011-01-28 13:15:276056 SessionDependencies session_deps;
6057 scoped_ptr<HttpTransaction> trans(
6058 new HttpNetworkTransaction(CreateSession(&session_deps)));
6059
[email protected]e22e1362009-11-23 21:31:126060 MockRead data_reads[] = {
6061 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6062 MockRead(false, OK),
6063 };
[email protected]9492e4a2010-02-24 00:58:466064
6065 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6066 session_deps.socket_factory.AddSocketDataProvider(&data);
6067
[email protected]f1f3f0f82011-10-01 20:38:106068 TestOldCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:466069
[email protected]5a1d7ca2010-04-28 20:12:276070 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466071 EXPECT_EQ(ERR_IO_PENDING, rv);
6072
6073 EXPECT_EQ(OK, callback.WaitForResult());
6074
6075 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506076 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:466077
6078 EXPECT_TRUE(response->headers != NULL);
6079 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6080
6081 std::string response_data;
6082 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f0e2bf42011-07-22 21:21:446083 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126084}
6085
[email protected]95d88ffe2010-02-04 21:25:336086TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336087 HttpRequestInfo request;
6088 request.method = "POST";
6089 request.url = GURL("http://www.google.com/upload");
6090 request.upload_data = new UploadData;
6091 request.load_flags = 0;
6092
[email protected]cb9bf6ca2011-01-28 13:15:276093 SessionDependencies session_deps;
6094 scoped_ptr<HttpTransaction> trans(
6095 new HttpNetworkTransaction(CreateSession(&session_deps)));
6096
[email protected]95d88ffe2010-02-04 21:25:336097 FilePath temp_file_path;
6098 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6099 const uint64 kFakeSize = 100000; // file is actually blank
6100
6101 std::vector<UploadData::Element> elements;
6102 UploadData::Element element;
6103 element.SetToFilePath(temp_file_path);
6104 element.SetContentLength(kFakeSize);
6105 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536106 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336107 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6108
6109 MockRead data_reads[] = {
6110 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6111 MockRead("hello world"),
6112 MockRead(false, OK),
6113 };
[email protected]31a2bfe2010-02-09 08:03:396114 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336115 session_deps.socket_factory.AddSocketDataProvider(&data);
6116
[email protected]f1f3f0f82011-10-01 20:38:106117 TestOldCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:336118
[email protected]5a1d7ca2010-04-28 20:12:276119 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336120 EXPECT_EQ(ERR_IO_PENDING, rv);
6121
6122 rv = callback.WaitForResult();
6123 EXPECT_EQ(OK, rv);
6124
6125 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506126 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:336127
6128 EXPECT_TRUE(response->headers != NULL);
6129 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6130
6131 std::string response_data;
6132 rv = ReadTransaction(trans.get(), &response_data);
6133 EXPECT_EQ(OK, rv);
6134 EXPECT_EQ("hello world", response_data);
6135
6136 file_util::Delete(temp_file_path, false);
6137}
6138
[email protected]6624b4622010-03-29 19:58:366139TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276140 HttpRequestInfo request;
6141 request.method = "POST";
6142 request.url = GURL("http://www.google.com/upload");
6143 request.upload_data = new UploadData;
6144 request.load_flags = 0;
6145
[email protected]6624b4622010-03-29 19:58:366146 // If we try to upload an unreadable file, the network stack should report
6147 // the file size as zero and upload zero bytes for that file.
6148 SessionDependencies session_deps;
6149 scoped_ptr<HttpTransaction> trans(
6150 new HttpNetworkTransaction(CreateSession(&session_deps)));
6151
6152 FilePath temp_file;
6153 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6154 std::string temp_file_content("Unreadable file.");
6155 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6156 temp_file_content.length()));
6157 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6158
[email protected]6624b4622010-03-29 19:58:366159 std::vector<UploadData::Element> elements;
6160 UploadData::Element element;
6161 element.SetToFilePath(temp_file);
6162 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536163 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366164
6165 MockRead data_reads[] = {
6166 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6167 MockRead(false, OK),
6168 };
6169 MockWrite data_writes[] = {
6170 MockWrite("POST /upload HTTP/1.1\r\n"
6171 "Host: www.google.com\r\n"
6172 "Connection: keep-alive\r\n"
6173 "Content-Length: 0\r\n\r\n"),
6174 MockWrite(false, OK),
6175 };
6176 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6177 arraysize(data_writes));
6178 session_deps.socket_factory.AddSocketDataProvider(&data);
6179
[email protected]f1f3f0f82011-10-01 20:38:106180 TestOldCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:366181
[email protected]5a1d7ca2010-04-28 20:12:276182 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366183 EXPECT_EQ(ERR_IO_PENDING, rv);
6184
6185 rv = callback.WaitForResult();
6186 EXPECT_EQ(OK, rv);
6187
6188 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506189 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366190 EXPECT_TRUE(response->headers != NULL);
6191 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6192
6193 file_util::Delete(temp_file, false);
6194}
6195
6196TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276197 HttpRequestInfo request;
6198 request.method = "POST";
6199 request.url = GURL("http://www.google.com/upload");
6200 request.upload_data = new UploadData;
6201 request.load_flags = 0;
6202
[email protected]6624b4622010-03-29 19:58:366203 SessionDependencies session_deps;
6204 scoped_ptr<HttpTransaction> trans(
6205 new HttpNetworkTransaction(CreateSession(&session_deps)));
6206
6207 FilePath temp_file;
6208 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6209 std::string temp_file_contents("Unreadable file.");
6210 std::string unreadable_contents(temp_file_contents.length(), '\0');
6211 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6212 temp_file_contents.length()));
6213
[email protected]6624b4622010-03-29 19:58:366214 std::vector<UploadData::Element> elements;
6215 UploadData::Element element;
6216 element.SetToFilePath(temp_file);
6217 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536218 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366219
6220 MockRead data_reads[] = {
6221 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6222 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6223 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6224
6225 MockRead("HTTP/1.1 200 OK\r\n"),
6226 MockRead("Content-Length: 0\r\n\r\n"),
6227 MockRead(false, OK),
6228 };
6229 MockWrite data_writes[] = {
6230 MockWrite("POST /upload HTTP/1.1\r\n"
6231 "Host: www.google.com\r\n"
6232 "Connection: keep-alive\r\n"
6233 "Content-Length: 16\r\n\r\n"),
6234 MockWrite(false, temp_file_contents.c_str()),
6235
6236 MockWrite("POST /upload HTTP/1.1\r\n"
6237 "Host: www.google.com\r\n"
6238 "Connection: keep-alive\r\n"
6239 "Content-Length: 16\r\n"
6240 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6241 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6242 MockWrite(false, OK),
6243 };
6244 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6245 arraysize(data_writes));
6246 session_deps.socket_factory.AddSocketDataProvider(&data);
6247
[email protected]f1f3f0f82011-10-01 20:38:106248 TestOldCompletionCallback callback1;
[email protected]6624b4622010-03-29 19:58:366249
[email protected]5a1d7ca2010-04-28 20:12:276250 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366251 EXPECT_EQ(ERR_IO_PENDING, rv);
6252
6253 rv = callback1.WaitForResult();
6254 EXPECT_EQ(OK, rv);
6255
6256 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:046257 ASSERT_TRUE(response != NULL);
6258 ASSERT_TRUE(response->headers != NULL);
[email protected]6624b4622010-03-29 19:58:366259 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
[email protected]79cb5c12011-09-12 13:12:046260 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]6624b4622010-03-29 19:58:366261
6262 // Now make the file unreadable and try again.
6263 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6264
[email protected]f1f3f0f82011-10-01 20:38:106265 TestOldCompletionCallback callback2;
[email protected]6624b4622010-03-29 19:58:366266
[email protected]f3cf9802011-10-28 18:44:586267 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]6624b4622010-03-29 19:58:366268 EXPECT_EQ(ERR_IO_PENDING, rv);
6269
6270 rv = callback2.WaitForResult();
6271 EXPECT_EQ(OK, rv);
6272
6273 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506274 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366275 EXPECT_TRUE(response->headers != NULL);
6276 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6277 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6278
6279 file_util::Delete(temp_file, false);
6280}
6281
[email protected]aeefc9e82010-02-19 16:18:276282// Tests that changes to Auth realms are treated like auth rejections.
6283TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6284 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276285
6286 HttpRequestInfo request;
6287 request.method = "GET";
6288 request.url = GURL("http://www.google.com/");
6289 request.load_flags = 0;
6290
6291 // First transaction will request a resource and receive a Basic challenge
6292 // with realm="first_realm".
6293 MockWrite data_writes1[] = {
6294 MockWrite("GET / HTTP/1.1\r\n"
6295 "Host: www.google.com\r\n"
6296 "Connection: keep-alive\r\n"
6297 "\r\n"),
6298 };
6299 MockRead data_reads1[] = {
6300 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6301 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6302 "\r\n"),
6303 };
6304
6305 // After calling trans->RestartWithAuth(), provide an Authentication header
6306 // for first_realm. The server will reject and provide a challenge with
6307 // second_realm.
6308 MockWrite data_writes2[] = {
6309 MockWrite("GET / HTTP/1.1\r\n"
6310 "Host: www.google.com\r\n"
6311 "Connection: keep-alive\r\n"
6312 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6313 "\r\n"),
6314 };
6315 MockRead data_reads2[] = {
6316 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6317 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6318 "\r\n"),
6319 };
6320
6321 // This again fails, and goes back to first_realm. Make sure that the
6322 // entry is removed from cache.
6323 MockWrite data_writes3[] = {
6324 MockWrite("GET / HTTP/1.1\r\n"
6325 "Host: www.google.com\r\n"
6326 "Connection: keep-alive\r\n"
6327 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6328 "\r\n"),
6329 };
6330 MockRead data_reads3[] = {
6331 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6332 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6333 "\r\n"),
6334 };
6335
6336 // Try one last time (with the correct password) and get the resource.
6337 MockWrite data_writes4[] = {
6338 MockWrite("GET / HTTP/1.1\r\n"
6339 "Host: www.google.com\r\n"
6340 "Connection: keep-alive\r\n"
6341 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6342 "\r\n"),
6343 };
6344 MockRead data_reads4[] = {
6345 MockRead("HTTP/1.1 200 OK\r\n"
6346 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506347 "Content-Length: 5\r\n"
6348 "\r\n"
6349 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276350 };
6351
6352 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6353 data_writes1, arraysize(data_writes1));
6354 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6355 data_writes2, arraysize(data_writes2));
6356 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6357 data_writes3, arraysize(data_writes3));
6358 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6359 data_writes4, arraysize(data_writes4));
6360 session_deps.socket_factory.AddSocketDataProvider(&data1);
6361 session_deps.socket_factory.AddSocketDataProvider(&data2);
6362 session_deps.socket_factory.AddSocketDataProvider(&data3);
6363 session_deps.socket_factory.AddSocketDataProvider(&data4);
6364
[email protected]f1f3f0f82011-10-01 20:38:106365 TestOldCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:276366
[email protected]0b0bf032010-09-21 18:08:506367 scoped_ptr<HttpTransaction> trans(
6368 new HttpNetworkTransaction(CreateSession(&session_deps)));
6369
[email protected]aeefc9e82010-02-19 16:18:276370 // Issue the first request with Authorize headers. There should be a
6371 // password prompt for first_realm waiting to be filled in after the
6372 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276373 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276374 EXPECT_EQ(ERR_IO_PENDING, rv);
6375 rv = callback1.WaitForResult();
6376 EXPECT_EQ(OK, rv);
6377 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506378 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046379 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6380 ASSERT_FALSE(challenge == NULL);
6381 EXPECT_FALSE(challenge->is_proxy);
6382 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6383 EXPECT_EQ("first_realm", challenge->realm);
6384 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276385
6386 // Issue the second request with an incorrect password. There should be a
6387 // password prompt for second_realm waiting to be filled in after the
6388 // transaction completes.
[email protected]f1f3f0f82011-10-01 20:38:106389 TestOldCompletionCallback callback2;
[email protected]f3cf9802011-10-28 18:44:586390 rv = trans->RestartWithAuth(AuthCredentials(kFirst, kBaz), &callback2);
[email protected]aeefc9e82010-02-19 16:18:276391 EXPECT_EQ(ERR_IO_PENDING, rv);
6392 rv = callback2.WaitForResult();
6393 EXPECT_EQ(OK, rv);
6394 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506395 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046396 challenge = response->auth_challenge.get();
6397 ASSERT_FALSE(challenge == NULL);
6398 EXPECT_FALSE(challenge->is_proxy);
6399 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6400 EXPECT_EQ("second_realm", challenge->realm);
6401 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276402
6403 // Issue the third request with another incorrect password. There should be
6404 // a password prompt for first_realm waiting to be filled in. If the password
6405 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6406 // first_realm was not correctly removed.
[email protected]f1f3f0f82011-10-01 20:38:106407 TestOldCompletionCallback callback3;
[email protected]f3cf9802011-10-28 18:44:586408 rv = trans->RestartWithAuth(AuthCredentials(kSecond, kFou), &callback3);
[email protected]aeefc9e82010-02-19 16:18:276409 EXPECT_EQ(ERR_IO_PENDING, rv);
6410 rv = callback3.WaitForResult();
6411 EXPECT_EQ(OK, rv);
6412 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506413 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046414 challenge = response->auth_challenge.get();
6415 ASSERT_FALSE(challenge == NULL);
6416 EXPECT_FALSE(challenge->is_proxy);
6417 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6418 EXPECT_EQ("first_realm", challenge->realm);
6419 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276420
6421 // Issue the fourth request with the correct password and username.
[email protected]f1f3f0f82011-10-01 20:38:106422 TestOldCompletionCallback callback4;
[email protected]f3cf9802011-10-28 18:44:586423 rv = trans->RestartWithAuth(AuthCredentials(kFirst, kBar), &callback4);
[email protected]aeefc9e82010-02-19 16:18:276424 EXPECT_EQ(ERR_IO_PENDING, rv);
6425 rv = callback4.WaitForResult();
6426 EXPECT_EQ(OK, rv);
6427 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506428 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:276429 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6430}
6431
[email protected]564b4912010-03-09 16:30:426432TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]5285d972011-10-18 18:56:346433 HttpStreamFactory::set_next_protos(MakeNextProtos("foo", "bar", NULL));
[email protected]8e6441ca2010-08-19 05:56:386434 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426435
[email protected]564b4912010-03-09 16:30:426436 SessionDependencies session_deps;
6437
6438 MockRead data_reads[] = {
6439 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356440 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426441 MockRead("hello world"),
6442 MockRead(false, OK),
6443 };
6444
6445 HttpRequestInfo request;
6446 request.method = "GET";
6447 request.url = GURL("http://www.google.com/");
6448 request.load_flags = 0;
6449
6450 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6451
6452 session_deps.socket_factory.AddSocketDataProvider(&data);
6453
[email protected]f1f3f0f82011-10-01 20:38:106454 TestOldCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426455
6456 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6457 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6458
[email protected]5a1d7ca2010-04-28 20:12:276459 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426460 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536461
[email protected]2fbaecf22010-07-22 22:20:356462 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]17291a022011-10-10 07:32:536463 const HttpServerProperties& http_server_properties =
6464 *session->http_server_properties();
[email protected]564b4912010-03-09 16:30:426465 EXPECT_FALSE(
[email protected]17291a022011-10-10 07:32:536466 http_server_properties.HasAlternateProtocol(http_host_port_pair));
[email protected]564b4912010-03-09 16:30:426467
6468 EXPECT_EQ(OK, callback.WaitForResult());
6469
6470 const HttpResponseInfo* response = trans->GetResponseInfo();
6471 ASSERT_TRUE(response != NULL);
6472 ASSERT_TRUE(response->headers != NULL);
6473 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536474 EXPECT_FALSE(response->was_fetched_via_spdy);
6475 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426476
6477 std::string response_data;
6478 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6479 EXPECT_EQ("hello world", response_data);
6480
[email protected]17291a022011-10-10 07:32:536481 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6482 const PortAlternateProtocolPair alternate =
6483 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6484 PortAlternateProtocolPair expected_alternate;
[email protected]564b4912010-03-09 16:30:426485 expected_alternate.port = 443;
[email protected]17291a022011-10-10 07:32:536486 expected_alternate.protocol = NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426487 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426488
[email protected]8e6441ca2010-08-19 05:56:386489 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]5285d972011-10-18 18:56:346490 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]564b4912010-03-09 16:30:426491}
6492
[email protected]8b95ed62011-03-18 18:12:036493TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386494 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426495 SessionDependencies session_deps;
6496
6497 HttpRequestInfo request;
6498 request.method = "GET";
6499 request.url = GURL("http://www.google.com/");
6500 request.load_flags = 0;
6501
6502 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6503 StaticSocketDataProvider first_data;
6504 first_data.set_connect_data(mock_connect);
6505 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6506
6507 MockRead data_reads[] = {
6508 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6509 MockRead("hello world"),
6510 MockRead(true, OK),
6511 };
6512 StaticSocketDataProvider second_data(
6513 data_reads, arraysize(data_reads), NULL, 0);
6514 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6515
[email protected]564b4912010-03-09 16:30:426516 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6517
[email protected]17291a022011-10-10 07:32:536518 HttpServerProperties* http_server_properties =
6519 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116520 // Port must be < 1024, or the header will be ignored (since initial port was
6521 // port 80 (another restricted port).
[email protected]17291a022011-10-10 07:32:536522 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116523 HostPortPair::FromURL(request.url),
6524 666 /* port is ignored by MockConnect anyway */,
[email protected]17291a022011-10-10 07:32:536525 NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426526
6527 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]3912662a32011-10-04 00:51:116528 TestOldCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426529
[email protected]5a1d7ca2010-04-28 20:12:276530 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426531 EXPECT_EQ(ERR_IO_PENDING, rv);
6532 EXPECT_EQ(OK, callback.WaitForResult());
6533
6534 const HttpResponseInfo* response = trans->GetResponseInfo();
6535 ASSERT_TRUE(response != NULL);
6536 ASSERT_TRUE(response->headers != NULL);
6537 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6538
6539 std::string response_data;
6540 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6541 EXPECT_EQ("hello world", response_data);
6542
[email protected]17291a022011-10-10 07:32:536543 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116544 HostPortPair::FromURL(request.url)));
[email protected]17291a022011-10-10 07:32:536545 const PortAlternateProtocolPair alternate =
6546 http_server_properties->GetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116547 HostPortPair::FromURL(request.url));
[email protected]17291a022011-10-10 07:32:536548 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386549 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426550}
6551
[email protected]3912662a32011-10-04 00:51:116552TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6553 // Ensure that we're not allowed to redirect traffic via an alternate
6554 // protocol to an unrestricted (port >= 1024) when the original traffic was
6555 // on a restricted port (port < 1024). Ensure that we can redirect in all
6556 // other cases.
6557 HttpStreamFactory::set_use_alternate_protocols(true);
6558 SessionDependencies session_deps;
6559
6560 HttpRequestInfo restricted_port_request;
6561 restricted_port_request.method = "GET";
6562 restricted_port_request.url = GURL("http://www.google.com:1023/");
6563 restricted_port_request.load_flags = 0;
6564
6565 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6566 StaticSocketDataProvider first_data;
6567 first_data.set_connect_data(mock_connect);
6568 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6569
6570 MockRead data_reads[] = {
6571 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6572 MockRead("hello world"),
6573 MockRead(true, OK),
6574 };
6575 StaticSocketDataProvider second_data(
6576 data_reads, arraysize(data_reads), NULL, 0);
6577 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6578
6579 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6580
[email protected]17291a022011-10-10 07:32:536581 HttpServerProperties* http_server_properties =
6582 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116583 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536584 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116585 HostPortPair::FromURL(restricted_port_request.url),
6586 kUnrestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536587 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116588
6589 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6590 TestOldCompletionCallback callback;
6591
6592 int rv = trans->Start(&restricted_port_request, &callback, BoundNetLog());
6593 EXPECT_EQ(ERR_IO_PENDING, rv);
6594 // Invalid change to unrestricted port should fail.
6595 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6596
6597 HttpStreamFactory::set_use_alternate_protocols(false);
6598}
6599
6600TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6601 // Ensure that we're not allowed to redirect traffic via an alternate
6602 // protocol to an unrestricted (port >= 1024) when the original traffic was
6603 // on a restricted port (port < 1024). Ensure that we can redirect in all
6604 // other cases.
6605 HttpStreamFactory::set_use_alternate_protocols(true);
6606 SessionDependencies session_deps;
6607
6608 HttpRequestInfo restricted_port_request;
6609 restricted_port_request.method = "GET";
6610 restricted_port_request.url = GURL("http://www.google.com:1023/");
6611 restricted_port_request.load_flags = 0;
6612
6613 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6614 StaticSocketDataProvider first_data;
6615 first_data.set_connect_data(mock_connect);
6616 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6617
6618 MockRead data_reads[] = {
6619 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6620 MockRead("hello world"),
6621 MockRead(true, OK),
6622 };
6623 StaticSocketDataProvider second_data(
6624 data_reads, arraysize(data_reads), NULL, 0);
6625 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6626
6627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6628
[email protected]17291a022011-10-10 07:32:536629 HttpServerProperties* http_server_properties =
6630 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116631 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536632 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116633 HostPortPair::FromURL(restricted_port_request.url),
6634 kRestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536635 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116636
6637 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6638 TestOldCompletionCallback callback;
6639
6640 int rv = trans->Start(&restricted_port_request, &callback, BoundNetLog());
6641 EXPECT_EQ(ERR_IO_PENDING, rv);
6642 // Valid change to restricted port should pass.
6643 EXPECT_EQ(OK, callback.WaitForResult());
6644
6645 HttpStreamFactory::set_use_alternate_protocols(false);
6646}
6647
6648TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6649 // Ensure that we're not allowed to redirect traffic via an alternate
6650 // protocol to an unrestricted (port >= 1024) when the original traffic was
6651 // on a restricted port (port < 1024). Ensure that we can redirect in all
6652 // other cases.
6653 HttpStreamFactory::set_use_alternate_protocols(true);
6654 SessionDependencies session_deps;
6655
6656 HttpRequestInfo unrestricted_port_request;
6657 unrestricted_port_request.method = "GET";
6658 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6659 unrestricted_port_request.load_flags = 0;
6660
6661 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6662 StaticSocketDataProvider first_data;
6663 first_data.set_connect_data(mock_connect);
6664 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6665
6666 MockRead data_reads[] = {
6667 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6668 MockRead("hello world"),
6669 MockRead(true, OK),
6670 };
6671 StaticSocketDataProvider second_data(
6672 data_reads, arraysize(data_reads), NULL, 0);
6673 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6674
6675 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6676
[email protected]17291a022011-10-10 07:32:536677 HttpServerProperties* http_server_properties =
6678 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116679 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536680 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116681 HostPortPair::FromURL(unrestricted_port_request.url),
6682 kRestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536683 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116684
6685 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6686 TestOldCompletionCallback callback;
6687
6688 int rv = trans->Start(&unrestricted_port_request, &callback, BoundNetLog());
6689 EXPECT_EQ(ERR_IO_PENDING, rv);
6690 // Valid change to restricted port should pass.
6691 EXPECT_EQ(OK, callback.WaitForResult());
6692
6693 HttpStreamFactory::set_use_alternate_protocols(false);
6694}
6695
6696TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6697 // Ensure that we're not allowed to redirect traffic via an alternate
6698 // protocol to an unrestricted (port >= 1024) when the original traffic was
6699 // on a restricted port (port < 1024). Ensure that we can redirect in all
6700 // other cases.
6701 HttpStreamFactory::set_use_alternate_protocols(true);
6702 SessionDependencies session_deps;
6703
6704 HttpRequestInfo unrestricted_port_request;
6705 unrestricted_port_request.method = "GET";
6706 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6707 unrestricted_port_request.load_flags = 0;
6708
6709 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6710 StaticSocketDataProvider first_data;
6711 first_data.set_connect_data(mock_connect);
6712 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6713
6714 MockRead data_reads[] = {
6715 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6716 MockRead("hello world"),
6717 MockRead(true, OK),
6718 };
6719 StaticSocketDataProvider second_data(
6720 data_reads, arraysize(data_reads), NULL, 0);
6721 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6722
6723 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6724
[email protected]17291a022011-10-10 07:32:536725 HttpServerProperties* http_server_properties =
6726 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116727 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536728 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116729 HostPortPair::FromURL(unrestricted_port_request.url),
6730 kUnrestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536731 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116732
6733 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6734 TestOldCompletionCallback callback;
6735
6736 int rv = trans->Start(&unrestricted_port_request, &callback, BoundNetLog());
6737 EXPECT_EQ(ERR_IO_PENDING, rv);
6738 // Valid change to an unrestricted port should pass.
6739 EXPECT_EQ(OK, callback.WaitForResult());
6740
6741 HttpStreamFactory::set_use_alternate_protocols(false);
6742}
6743
[email protected]2ff8b312010-04-26 22:20:546744TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386745 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346746 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:546747 SessionDependencies session_deps;
6748
6749 HttpRequestInfo request;
6750 request.method = "GET";
6751 request.url = GURL("http://www.google.com/");
6752 request.load_flags = 0;
6753
6754 MockRead data_reads[] = {
6755 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356756 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546757 MockRead("hello world"),
6758 MockRead(true, OK),
6759 };
6760
6761 StaticSocketDataProvider first_transaction(
6762 data_reads, arraysize(data_reads), NULL, 0);
6763 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6764
6765 SSLSocketDataProvider ssl(true, OK);
6766 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356767 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536768 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546769 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6770
[email protected]2bd93022010-07-17 00:58:446771 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136772 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546773
[email protected]2bd93022010-07-17 00:58:446774 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6775 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546776 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136777 CreateMockRead(*resp),
6778 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546779 MockRead(true, 0, 0),
6780 };
6781
6782 scoped_refptr<DelayedSocketData> spdy_data(
6783 new DelayedSocketData(
6784 1, // wait for one write to finish before reading.
6785 spdy_reads, arraysize(spdy_reads),
6786 spdy_writes, arraysize(spdy_writes)));
6787 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6788
[email protected]2d6728692011-03-12 01:39:556789 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6790 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6791 NULL, 0, NULL, 0);
6792 hanging_non_alternate_protocol_socket.set_connect_data(
6793 never_finishing_connect);
6794 session_deps.socket_factory.AddSocketDataProvider(
6795 &hanging_non_alternate_protocol_socket);
6796
[email protected]f1f3f0f82011-10-01 20:38:106797 TestOldCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:546798
6799 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6800 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6801
[email protected]5a1d7ca2010-04-28 20:12:276802 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546803 EXPECT_EQ(ERR_IO_PENDING, rv);
6804 EXPECT_EQ(OK, callback.WaitForResult());
6805
6806 const HttpResponseInfo* response = trans->GetResponseInfo();
6807 ASSERT_TRUE(response != NULL);
6808 ASSERT_TRUE(response->headers != NULL);
6809 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6810
6811 std::string response_data;
6812 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6813 EXPECT_EQ("hello world", response_data);
6814
6815 trans.reset(new HttpNetworkTransaction(session));
6816
[email protected]5a1d7ca2010-04-28 20:12:276817 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546818 EXPECT_EQ(ERR_IO_PENDING, rv);
6819 EXPECT_EQ(OK, callback.WaitForResult());
6820
6821 response = trans->GetResponseInfo();
6822 ASSERT_TRUE(response != NULL);
6823 ASSERT_TRUE(response->headers != NULL);
6824 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536825 EXPECT_TRUE(response->was_fetched_via_spdy);
6826 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546827
6828 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6829 EXPECT_EQ("hello!", response_data);
6830
[email protected]5285d972011-10-18 18:56:346831 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:386832 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546833}
6834
[email protected]2d6728692011-03-12 01:39:556835TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6836 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346837 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556838 SessionDependencies session_deps;
6839
6840 HttpRequestInfo request;
6841 request.method = "GET";
6842 request.url = GURL("http://www.google.com/");
6843 request.load_flags = 0;
6844
6845 MockRead data_reads[] = {
6846 MockRead("HTTP/1.1 200 OK\r\n"),
6847 MockRead(kAlternateProtocolHttpHeader),
6848 MockRead("hello world"),
6849 MockRead(true, OK),
6850 };
6851
6852 StaticSocketDataProvider first_transaction(
6853 data_reads, arraysize(data_reads), NULL, 0);
6854 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6855 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6856
6857 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6858 StaticSocketDataProvider hanging_socket(
6859 NULL, 0, NULL, 0);
6860 hanging_socket.set_connect_data(never_finishing_connect);
6861 // Socket 2 and 3 are the hanging Alternate-Protocol and
6862 // non-Alternate-Protocol jobs from the 2nd transaction.
6863 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6864 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6865
6866 SSLSocketDataProvider ssl(true, OK);
6867 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6868 ssl.next_proto = "spdy/2";
6869 ssl.was_npn_negotiated = true;
6870 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6871
6872 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6873 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6874 MockWrite spdy_writes[] = {
6875 CreateMockWrite(*req1),
6876 CreateMockWrite(*req2),
6877 };
6878 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6879 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6880 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6881 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6882 MockRead spdy_reads[] = {
6883 CreateMockRead(*resp1),
6884 CreateMockRead(*data1),
6885 CreateMockRead(*resp2),
6886 CreateMockRead(*data2),
6887 MockRead(true, 0, 0),
6888 };
6889
6890 scoped_refptr<DelayedSocketData> spdy_data(
6891 new DelayedSocketData(
6892 2, // wait for writes to finish before reading.
6893 spdy_reads, arraysize(spdy_reads),
6894 spdy_writes, arraysize(spdy_writes)));
6895 // Socket 4 is the successful Alternate-Protocol for transaction 3.
6896 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6897
6898 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6899 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6900
6901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f1f3f0f82011-10-01 20:38:106902 TestOldCompletionCallback callback1;
[email protected]2d6728692011-03-12 01:39:556903 HttpNetworkTransaction trans1(session);
6904
6905 int rv = trans1.Start(&request, &callback1, BoundNetLog());
6906 EXPECT_EQ(ERR_IO_PENDING, rv);
6907 EXPECT_EQ(OK, callback1.WaitForResult());
6908
6909 const HttpResponseInfo* response = trans1.GetResponseInfo();
6910 ASSERT_TRUE(response != NULL);
6911 ASSERT_TRUE(response->headers != NULL);
6912 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6913
6914 std::string response_data;
6915 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6916 EXPECT_EQ("hello world", response_data);
6917
[email protected]f1f3f0f82011-10-01 20:38:106918 TestOldCompletionCallback callback2;
[email protected]2d6728692011-03-12 01:39:556919 HttpNetworkTransaction trans2(session);
6920 rv = trans2.Start(&request, &callback2, BoundNetLog());
6921 EXPECT_EQ(ERR_IO_PENDING, rv);
6922
[email protected]f1f3f0f82011-10-01 20:38:106923 TestOldCompletionCallback callback3;
[email protected]2d6728692011-03-12 01:39:556924 HttpNetworkTransaction trans3(session);
6925 rv = trans3.Start(&request, &callback3, BoundNetLog());
6926 EXPECT_EQ(ERR_IO_PENDING, rv);
6927
6928 EXPECT_EQ(OK, callback2.WaitForResult());
6929 EXPECT_EQ(OK, callback3.WaitForResult());
6930
6931 response = trans2.GetResponseInfo();
6932 ASSERT_TRUE(response != NULL);
6933 ASSERT_TRUE(response->headers != NULL);
6934 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6935 EXPECT_TRUE(response->was_fetched_via_spdy);
6936 EXPECT_TRUE(response->was_npn_negotiated);
6937 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6938 EXPECT_EQ("hello!", response_data);
6939
6940 response = trans3.GetResponseInfo();
6941 ASSERT_TRUE(response != NULL);
6942 ASSERT_TRUE(response->headers != NULL);
6943 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6944 EXPECT_TRUE(response->was_fetched_via_spdy);
6945 EXPECT_TRUE(response->was_npn_negotiated);
6946 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6947 EXPECT_EQ("hello!", response_data);
6948
[email protected]5285d972011-10-18 18:56:346949 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:556950 HttpStreamFactory::set_use_alternate_protocols(false);
6951}
6952
6953TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6954 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346955 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556956 SessionDependencies session_deps;
6957
6958 HttpRequestInfo request;
6959 request.method = "GET";
6960 request.url = GURL("http://www.google.com/");
6961 request.load_flags = 0;
6962
6963 MockRead data_reads[] = {
6964 MockRead("HTTP/1.1 200 OK\r\n"),
6965 MockRead(kAlternateProtocolHttpHeader),
6966 MockRead("hello world"),
6967 MockRead(true, OK),
6968 };
6969
6970 StaticSocketDataProvider first_transaction(
6971 data_reads, arraysize(data_reads), NULL, 0);
6972 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6973
6974 SSLSocketDataProvider ssl(true, OK);
6975 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6976 ssl.next_proto = "spdy/2";
6977 ssl.was_npn_negotiated = true;
6978 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6979
6980 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6981 StaticSocketDataProvider hanging_alternate_protocol_socket(
6982 NULL, 0, NULL, 0);
6983 hanging_alternate_protocol_socket.set_connect_data(
6984 never_finishing_connect);
6985 session_deps.socket_factory.AddSocketDataProvider(
6986 &hanging_alternate_protocol_socket);
6987
6988 // 2nd request is just a copy of the first one, over HTTP again.
6989 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6990
[email protected]f1f3f0f82011-10-01 20:38:106991 TestOldCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:556992
6993 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6994 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6995
6996 int rv = trans->Start(&request, &callback, BoundNetLog());
6997 EXPECT_EQ(ERR_IO_PENDING, rv);
6998 EXPECT_EQ(OK, callback.WaitForResult());
6999
7000 const HttpResponseInfo* response = trans->GetResponseInfo();
7001 ASSERT_TRUE(response != NULL);
7002 ASSERT_TRUE(response->headers != NULL);
7003 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7004
7005 std::string response_data;
7006 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7007 EXPECT_EQ("hello world", response_data);
7008
7009 trans.reset(new HttpNetworkTransaction(session));
7010
7011 rv = trans->Start(&request, &callback, BoundNetLog());
7012 EXPECT_EQ(ERR_IO_PENDING, rv);
7013 EXPECT_EQ(OK, callback.WaitForResult());
7014
7015 response = trans->GetResponseInfo();
7016 ASSERT_TRUE(response != NULL);
7017 ASSERT_TRUE(response->headers != NULL);
7018 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7019 EXPECT_FALSE(response->was_fetched_via_spdy);
7020 EXPECT_FALSE(response->was_npn_negotiated);
7021
7022 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7023 EXPECT_EQ("hello world", response_data);
7024
[email protected]5285d972011-10-18 18:56:347025 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557026 HttpStreamFactory::set_use_alternate_protocols(false);
7027}
7028
[email protected]631f1322010-04-30 17:59:117029class CapturingProxyResolver : public ProxyResolver {
7030 public:
7031 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7032 virtual ~CapturingProxyResolver() {}
7033
7034 virtual int GetProxyForURL(const GURL& url,
7035 ProxyInfo* results,
[email protected]f1f3f0f82011-10-01 20:38:107036 OldCompletionCallback* callback,
[email protected]631f1322010-04-30 17:59:117037 RequestHandle* request,
7038 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:407039 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7040 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:427041 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:117042 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:427043 return OK;
[email protected]631f1322010-04-30 17:59:117044 }
7045
7046 virtual void CancelRequest(RequestHandle request) {
7047 NOTREACHED();
7048 }
7049
[email protected]f2c971f2011-11-08 00:33:177050 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
7051 NOTREACHED();
7052 return LOAD_STATE_IDLE;
7053 }
7054
7055 virtual LoadState GetLoadStateThreadSafe(
7056 RequestHandle request) const OVERRIDE {
7057 NOTREACHED();
7058 return LOAD_STATE_IDLE;
7059 }
7060
[email protected]1e605472010-12-16 21:41:407061 virtual void CancelSetPacScript() {
7062 NOTREACHED();
7063 }
7064
[email protected]24476402010-07-20 20:55:177065 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]f1f3f0f82011-10-01 20:38:107066 OldCompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:427067 return OK;
[email protected]631f1322010-04-30 17:59:117068 }
7069
[email protected]24476402010-07-20 20:55:177070 const std::vector<GURL>& resolved() const { return resolved_; }
7071
7072 private:
[email protected]631f1322010-04-30 17:59:117073 std::vector<GURL> resolved_;
7074
7075 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7076};
7077
[email protected]631f1322010-04-30 17:59:117078TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:387079 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347080 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]631f1322010-04-30 17:59:117081
7082 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:427083 proxy_config.set_auto_detect(true);
7084 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:117085
[email protected]631f1322010-04-30 17:59:117086 CapturingProxyResolver* capturing_proxy_resolver =
7087 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:387088 SessionDependencies session_deps(new ProxyService(
7089 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7090 NULL));
[email protected]631f1322010-04-30 17:59:117091
7092 HttpRequestInfo request;
7093 request.method = "GET";
7094 request.url = GURL("http://www.google.com/");
7095 request.load_flags = 0;
7096
7097 MockRead data_reads[] = {
7098 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357099 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:117100 MockRead("hello world"),
7101 MockRead(true, OK),
7102 };
7103
7104 StaticSocketDataProvider first_transaction(
7105 data_reads, arraysize(data_reads), NULL, 0);
7106 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7107
7108 SSLSocketDataProvider ssl(true, OK);
7109 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357110 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537111 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:117112 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7113
[email protected]2bd93022010-07-17 00:58:447114 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:117115 MockWrite spdy_writes[] = {
7116 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7117 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:427118 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:137119 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:117120 };
7121
[email protected]d911f1b2010-05-05 22:39:427122 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7123
[email protected]2bd93022010-07-17 00:58:447124 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7125 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:117126 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:427127 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:137128 CreateMockRead(*resp.get(), 4), // 2, 4
7129 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:427130 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:117131 };
7132
[email protected]d911f1b2010-05-05 22:39:427133 scoped_refptr<OrderedSocketData> spdy_data(
7134 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:117135 spdy_reads, arraysize(spdy_reads),
7136 spdy_writes, arraysize(spdy_writes)));
7137 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7138
[email protected]2d6728692011-03-12 01:39:557139 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7140 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7141 NULL, 0, NULL, 0);
7142 hanging_non_alternate_protocol_socket.set_connect_data(
7143 never_finishing_connect);
7144 session_deps.socket_factory.AddSocketDataProvider(
7145 &hanging_non_alternate_protocol_socket);
7146
[email protected]f1f3f0f82011-10-01 20:38:107147 TestOldCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:117148
7149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7150 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7151
7152 int rv = trans->Start(&request, &callback, BoundNetLog());
7153 EXPECT_EQ(ERR_IO_PENDING, rv);
7154 EXPECT_EQ(OK, callback.WaitForResult());
7155
7156 const HttpResponseInfo* response = trans->GetResponseInfo();
7157 ASSERT_TRUE(response != NULL);
7158 ASSERT_TRUE(response->headers != NULL);
7159 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537160 EXPECT_FALSE(response->was_fetched_via_spdy);
7161 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117162
7163 std::string response_data;
7164 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7165 EXPECT_EQ("hello world", response_data);
7166
7167 trans.reset(new HttpNetworkTransaction(session));
7168
7169 rv = trans->Start(&request, &callback, BoundNetLog());
7170 EXPECT_EQ(ERR_IO_PENDING, rv);
7171 EXPECT_EQ(OK, callback.WaitForResult());
7172
7173 response = trans->GetResponseInfo();
7174 ASSERT_TRUE(response != NULL);
7175 ASSERT_TRUE(response->headers != NULL);
7176 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537177 EXPECT_TRUE(response->was_fetched_via_spdy);
7178 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117179
7180 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7181 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557182 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427183 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117184 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427185 EXPECT_EQ("https://www.google.com/",
7186 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117187
[email protected]5285d972011-10-18 18:56:347188 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387189 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117190}
[email protected]631f1322010-04-30 17:59:117191
[email protected]2ff8b312010-04-26 22:20:547192TEST_F(HttpNetworkTransactionTest,
7193 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387194 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347195 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:547196 SessionDependencies session_deps;
7197
7198 HttpRequestInfo request;
7199 request.method = "GET";
7200 request.url = GURL("http://www.google.com/");
7201 request.load_flags = 0;
7202
7203 MockRead data_reads[] = {
7204 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357205 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547206 MockRead("hello world"),
7207 MockRead(true, OK),
7208 };
7209
7210 StaticSocketDataProvider first_transaction(
7211 data_reads, arraysize(data_reads), NULL, 0);
7212 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7213
7214 SSLSocketDataProvider ssl(true, OK);
7215 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357216 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537217 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:547218 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537219 // Make sure we use ssl for spdy here.
7220 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547221
[email protected]2bd93022010-07-17 00:58:447222 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137223 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547224
[email protected]2bd93022010-07-17 00:58:447225 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7226 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547227 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137228 CreateMockRead(*resp),
7229 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547230 MockRead(true, 0, 0),
7231 };
7232
7233 scoped_refptr<DelayedSocketData> spdy_data(
7234 new DelayedSocketData(
7235 1, // wait for one write to finish before reading.
7236 spdy_reads, arraysize(spdy_reads),
7237 spdy_writes, arraysize(spdy_writes)));
7238 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7239
[email protected]f1f3f0f82011-10-01 20:38:107240 TestOldCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:547241
7242 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7243
7244 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7245
[email protected]5a1d7ca2010-04-28 20:12:277246 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547247 EXPECT_EQ(ERR_IO_PENDING, rv);
7248 EXPECT_EQ(OK, callback.WaitForResult());
7249
7250 const HttpResponseInfo* response = trans->GetResponseInfo();
7251 ASSERT_TRUE(response != NULL);
7252 ASSERT_TRUE(response->headers != NULL);
7253 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7254
7255 std::string response_data;
7256 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7257 EXPECT_EQ("hello world", response_data);
7258
7259 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387260 HostPortPair host_port_pair("www.google.com", 443);
7261 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547262 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317263 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287264 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:297265 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]02b0c342010-09-25 21:09:387266
7267 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7268 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287269 connection->Init(host_port_pair.ToString(),
7270 transport_params,
7271 LOWEST,
7272 &callback,
7273 session->transport_socket_pool(),
[email protected]02b0c342010-09-25 21:09:387274 BoundNetLog()));
7275 EXPECT_EQ(OK, callback.WaitForResult());
7276
7277 SSLConfig ssl_config;
7278 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347279 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177280 SSLClientSocketContext context;
7281 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347282 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7283 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177284 NULL /* ssl_host_info */, context));
[email protected]9e1bdd32011-02-03 21:48:347285 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:387286 EXPECT_EQ(OK, callback.WaitForResult());
7287
[email protected]9e1bdd32011-02-03 21:48:347288 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387289 true, OK));
7290
[email protected]2ff8b312010-04-26 22:20:547291 trans.reset(new HttpNetworkTransaction(session));
7292
[email protected]5a1d7ca2010-04-28 20:12:277293 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547294 EXPECT_EQ(ERR_IO_PENDING, rv);
7295 EXPECT_EQ(OK, callback.WaitForResult());
7296
7297 response = trans->GetResponseInfo();
7298 ASSERT_TRUE(response != NULL);
7299 ASSERT_TRUE(response->headers != NULL);
7300 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537301 EXPECT_TRUE(response->was_fetched_via_spdy);
7302 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547303
7304 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7305 EXPECT_EQ("hello!", response_data);
7306
[email protected]5285d972011-10-18 18:56:347307 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387308 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427309}
7310
[email protected]044de0642010-06-17 10:42:157311// GenerateAuthToken is a mighty big test.
7312// It tests all permutation of GenerateAuthToken behavior:
7313// - Synchronous and Asynchronous completion.
7314// - OK or error on completion.
7315// - Direct connection, non-authenticating proxy, and authenticating proxy.
7316// - HTTP or HTTPS backend (to include proxy tunneling).
7317// - Non-authenticating and authenticating backend.
7318//
7319// In all, there are 44 reasonable permuations (for example, if there are
7320// problems generating an auth token for an authenticating proxy, we don't
7321// need to test all permutations of the backend server).
7322//
7323// The test proceeds by going over each of the configuration cases, and
7324// potentially running up to three rounds in each of the tests. The TestConfig
7325// specifies both the configuration for the test as well as the expectations
7326// for the results.
7327TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507328 static const char kServer[] = "http://www.example.com";
7329 static const char kSecureServer[] = "https://www.example.com";
7330 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157331 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7332
7333 enum AuthTiming {
7334 AUTH_NONE,
7335 AUTH_SYNC,
7336 AUTH_ASYNC,
7337 };
7338
7339 const MockWrite kGet(
7340 "GET / HTTP/1.1\r\n"
7341 "Host: www.example.com\r\n"
7342 "Connection: keep-alive\r\n\r\n");
7343 const MockWrite kGetProxy(
7344 "GET http://www.example.com/ HTTP/1.1\r\n"
7345 "Host: www.example.com\r\n"
7346 "Proxy-Connection: keep-alive\r\n\r\n");
7347 const MockWrite kGetAuth(
7348 "GET / HTTP/1.1\r\n"
7349 "Host: www.example.com\r\n"
7350 "Connection: keep-alive\r\n"
7351 "Authorization: auth_token\r\n\r\n");
7352 const MockWrite kGetProxyAuth(
7353 "GET http://www.example.com/ HTTP/1.1\r\n"
7354 "Host: www.example.com\r\n"
7355 "Proxy-Connection: keep-alive\r\n"
7356 "Proxy-Authorization: auth_token\r\n\r\n");
7357 const MockWrite kGetAuthThroughProxy(
7358 "GET http://www.example.com/ HTTP/1.1\r\n"
7359 "Host: www.example.com\r\n"
7360 "Proxy-Connection: keep-alive\r\n"
7361 "Authorization: auth_token\r\n\r\n");
7362 const MockWrite kGetAuthWithProxyAuth(
7363 "GET http://www.example.com/ HTTP/1.1\r\n"
7364 "Host: www.example.com\r\n"
7365 "Proxy-Connection: keep-alive\r\n"
7366 "Proxy-Authorization: auth_token\r\n"
7367 "Authorization: auth_token\r\n\r\n");
7368 const MockWrite kConnect(
7369 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7370 "Host: www.example.com\r\n"
7371 "Proxy-Connection: keep-alive\r\n\r\n");
7372 const MockWrite kConnectProxyAuth(
7373 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7374 "Host: www.example.com\r\n"
7375 "Proxy-Connection: keep-alive\r\n"
7376 "Proxy-Authorization: auth_token\r\n\r\n");
7377
7378 const MockRead kSuccess(
7379 "HTTP/1.1 200 OK\r\n"
7380 "Content-Type: text/html; charset=iso-8859-1\r\n"
7381 "Content-Length: 3\r\n\r\n"
7382 "Yes");
7383 const MockRead kFailure(
7384 "Should not be called.");
7385 const MockRead kServerChallenge(
7386 "HTTP/1.1 401 Unauthorized\r\n"
7387 "WWW-Authenticate: Mock realm=server\r\n"
7388 "Content-Type: text/html; charset=iso-8859-1\r\n"
7389 "Content-Length: 14\r\n\r\n"
7390 "Unauthorized\r\n");
7391 const MockRead kProxyChallenge(
7392 "HTTP/1.1 407 Unauthorized\r\n"
7393 "Proxy-Authenticate: Mock realm=proxy\r\n"
7394 "Proxy-Connection: close\r\n"
7395 "Content-Type: text/html; charset=iso-8859-1\r\n"
7396 "Content-Length: 14\r\n\r\n"
7397 "Unauthorized\r\n");
7398 const MockRead kProxyConnected(
7399 "HTTP/1.1 200 Connection Established\r\n\r\n");
7400
7401 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7402 // no constructors, but the C++ compiler on Windows warns about
7403 // unspecified data in compound literals. So, moved to using constructors,
7404 // and TestRound's created with the default constructor should not be used.
7405 struct TestRound {
7406 TestRound()
7407 : expected_rv(ERR_UNEXPECTED),
7408 extra_write(NULL),
7409 extra_read(NULL) {
7410 }
7411 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7412 int expected_rv_arg)
7413 : write(write_arg),
7414 read(read_arg),
7415 expected_rv(expected_rv_arg),
7416 extra_write(NULL),
7417 extra_read(NULL) {
7418 }
7419 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7420 int expected_rv_arg, const MockWrite* extra_write_arg,
7421 const MockWrite* extra_read_arg)
7422 : write(write_arg),
7423 read(read_arg),
7424 expected_rv(expected_rv_arg),
7425 extra_write(extra_write_arg),
7426 extra_read(extra_read_arg) {
7427 }
7428 MockWrite write;
7429 MockRead read;
7430 int expected_rv;
7431 const MockWrite* extra_write;
7432 const MockRead* extra_read;
7433 };
7434
7435 static const int kNoSSL = 500;
7436
7437 struct TestConfig {
7438 const char* proxy_url;
7439 AuthTiming proxy_auth_timing;
7440 int proxy_auth_rv;
7441 const char* server_url;
7442 AuthTiming server_auth_timing;
7443 int server_auth_rv;
7444 int num_auth_rounds;
7445 int first_ssl_round;
7446 TestRound rounds[3];
7447 } test_configs[] = {
7448 // Non-authenticating HTTP server with a direct connection.
7449 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7450 { TestRound(kGet, kSuccess, OK)}},
7451 // Authenticating HTTP server with a direct connection.
7452 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7453 { TestRound(kGet, kServerChallenge, OK),
7454 TestRound(kGetAuth, kSuccess, OK)}},
7455 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7456 { TestRound(kGet, kServerChallenge, OK),
7457 TestRound(kGetAuth, kFailure, kAuthErr)}},
7458 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7459 { TestRound(kGet, kServerChallenge, OK),
7460 TestRound(kGetAuth, kSuccess, OK)}},
7461 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7462 { TestRound(kGet, kServerChallenge, OK),
7463 TestRound(kGetAuth, kFailure, kAuthErr)}},
7464 // Non-authenticating HTTP server through a non-authenticating proxy.
7465 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7466 { TestRound(kGetProxy, kSuccess, OK)}},
7467 // Authenticating HTTP server through a non-authenticating proxy.
7468 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7469 { TestRound(kGetProxy, kServerChallenge, OK),
7470 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7471 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7472 { TestRound(kGetProxy, kServerChallenge, OK),
7473 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7474 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7475 { TestRound(kGetProxy, kServerChallenge, OK),
7476 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7477 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7478 { TestRound(kGetProxy, kServerChallenge, OK),
7479 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7480 // Non-authenticating HTTP server through an authenticating proxy.
7481 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7482 { TestRound(kGetProxy, kProxyChallenge, OK),
7483 TestRound(kGetProxyAuth, kSuccess, OK)}},
7484 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7485 { TestRound(kGetProxy, kProxyChallenge, OK),
7486 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7487 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7488 { TestRound(kGetProxy, kProxyChallenge, OK),
7489 TestRound(kGetProxyAuth, kSuccess, OK)}},
7490 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7491 { TestRound(kGetProxy, kProxyChallenge, OK),
7492 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7493 // Authenticating HTTP server through an authenticating proxy.
7494 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7495 { TestRound(kGetProxy, kProxyChallenge, OK),
7496 TestRound(kGetProxyAuth, kServerChallenge, OK),
7497 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7498 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7499 { TestRound(kGetProxy, kProxyChallenge, OK),
7500 TestRound(kGetProxyAuth, kServerChallenge, OK),
7501 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7502 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7503 { TestRound(kGetProxy, kProxyChallenge, OK),
7504 TestRound(kGetProxyAuth, kServerChallenge, OK),
7505 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7506 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7507 { TestRound(kGetProxy, kProxyChallenge, OK),
7508 TestRound(kGetProxyAuth, kServerChallenge, OK),
7509 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7510 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7511 { TestRound(kGetProxy, kProxyChallenge, OK),
7512 TestRound(kGetProxyAuth, kServerChallenge, OK),
7513 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7514 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7515 { TestRound(kGetProxy, kProxyChallenge, OK),
7516 TestRound(kGetProxyAuth, kServerChallenge, OK),
7517 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7518 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7519 { TestRound(kGetProxy, kProxyChallenge, OK),
7520 TestRound(kGetProxyAuth, kServerChallenge, OK),
7521 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7522 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7523 { TestRound(kGetProxy, kProxyChallenge, OK),
7524 TestRound(kGetProxyAuth, kServerChallenge, OK),
7525 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7526 // Non-authenticating HTTPS server with a direct connection.
7527 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7528 { TestRound(kGet, kSuccess, OK)}},
7529 // Authenticating HTTPS server with a direct connection.
7530 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7531 { TestRound(kGet, kServerChallenge, OK),
7532 TestRound(kGetAuth, kSuccess, OK)}},
7533 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7534 { TestRound(kGet, kServerChallenge, OK),
7535 TestRound(kGetAuth, kFailure, kAuthErr)}},
7536 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7537 { TestRound(kGet, kServerChallenge, OK),
7538 TestRound(kGetAuth, kSuccess, OK)}},
7539 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7540 { TestRound(kGet, kServerChallenge, OK),
7541 TestRound(kGetAuth, kFailure, kAuthErr)}},
7542 // Non-authenticating HTTPS server with a non-authenticating proxy.
7543 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7544 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7545 // Authenticating HTTPS server through a non-authenticating proxy.
7546 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7547 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7548 TestRound(kGetAuth, kSuccess, OK)}},
7549 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7550 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7551 TestRound(kGetAuth, kFailure, kAuthErr)}},
7552 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7553 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7554 TestRound(kGetAuth, kSuccess, OK)}},
7555 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7556 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7557 TestRound(kGetAuth, kFailure, kAuthErr)}},
7558 // Non-Authenticating HTTPS server through an authenticating proxy.
7559 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7560 { TestRound(kConnect, kProxyChallenge, OK),
7561 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7562 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7563 { TestRound(kConnect, kProxyChallenge, OK),
7564 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7565 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7566 { TestRound(kConnect, kProxyChallenge, OK),
7567 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7568 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7569 { TestRound(kConnect, kProxyChallenge, OK),
7570 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7571 // Authenticating HTTPS server through an authenticating proxy.
7572 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7573 { TestRound(kConnect, kProxyChallenge, OK),
7574 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7575 &kGet, &kServerChallenge),
7576 TestRound(kGetAuth, kSuccess, OK)}},
7577 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7578 { TestRound(kConnect, kProxyChallenge, OK),
7579 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7580 &kGet, &kServerChallenge),
7581 TestRound(kGetAuth, kFailure, kAuthErr)}},
7582 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7583 { TestRound(kConnect, kProxyChallenge, OK),
7584 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7585 &kGet, &kServerChallenge),
7586 TestRound(kGetAuth, kSuccess, OK)}},
7587 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7588 { TestRound(kConnect, kProxyChallenge, OK),
7589 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7590 &kGet, &kServerChallenge),
7591 TestRound(kGetAuth, kFailure, kAuthErr)}},
7592 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7593 { TestRound(kConnect, kProxyChallenge, OK),
7594 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7595 &kGet, &kServerChallenge),
7596 TestRound(kGetAuth, kSuccess, OK)}},
7597 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7598 { TestRound(kConnect, kProxyChallenge, OK),
7599 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7600 &kGet, &kServerChallenge),
7601 TestRound(kGetAuth, kFailure, kAuthErr)}},
7602 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7603 { TestRound(kConnect, kProxyChallenge, OK),
7604 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7605 &kGet, &kServerChallenge),
7606 TestRound(kGetAuth, kSuccess, OK)}},
7607 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7608 { TestRound(kConnect, kProxyChallenge, OK),
7609 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7610 &kGet, &kServerChallenge),
7611 TestRound(kGetAuth, kFailure, kAuthErr)}},
7612 };
7613
7614 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157615 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087616 HttpAuthHandlerMock::Factory* auth_factory(
7617 new HttpAuthHandlerMock::Factory());
7618 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157619 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267620
7621 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157622 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087623 for (int n = 0; n < 2; n++) {
7624 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7625 std::string auth_challenge = "Mock realm=proxy";
7626 GURL origin(test_config.proxy_url);
7627 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7628 auth_challenge.end());
7629 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7630 origin, BoundNetLog());
7631 auth_handler->SetGenerateExpectation(
7632 test_config.proxy_auth_timing == AUTH_ASYNC,
7633 test_config.proxy_auth_rv);
7634 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7635 }
[email protected]044de0642010-06-17 10:42:157636 }
7637 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007638 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157639 std::string auth_challenge = "Mock realm=server";
7640 GURL origin(test_config.server_url);
7641 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7642 auth_challenge.end());
7643 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7644 origin, BoundNetLog());
7645 auth_handler->SetGenerateExpectation(
7646 test_config.server_auth_timing == AUTH_ASYNC,
7647 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087648 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157649 }
7650 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127651 session_deps.proxy_service.reset(
7652 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157653 } else {
[email protected]6104ea5d2011-04-27 21:37:127654 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157655 }
7656
7657 HttpRequestInfo request;
7658 request.method = "GET";
7659 request.url = GURL(test_config.server_url);
7660 request.load_flags = 0;
7661
[email protected]0b0bf032010-09-21 18:08:507662 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7663 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157664
7665 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7666 const TestRound& read_write_round = test_config.rounds[round];
7667
7668 // Set up expected reads and writes.
7669 MockRead reads[2];
7670 reads[0] = read_write_round.read;
7671 size_t length_reads = 1;
7672 if (read_write_round.extra_read) {
7673 reads[1] = *read_write_round.extra_read;
7674 length_reads = 2;
7675 }
7676
7677 MockWrite writes[2];
7678 writes[0] = read_write_round.write;
7679 size_t length_writes = 1;
7680 if (read_write_round.extra_write) {
7681 writes[1] = *read_write_round.extra_write;
7682 length_writes = 2;
7683 }
7684 StaticSocketDataProvider data_provider(
7685 reads, length_reads, writes, length_writes);
7686 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7687
7688 // Add an SSL sequence if necessary.
7689 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7690 if (round >= test_config.first_ssl_round)
7691 session_deps.socket_factory.AddSSLSocketDataProvider(
7692 &ssl_socket_data_provider);
7693
7694 // Start or restart the transaction.
[email protected]f1f3f0f82011-10-01 20:38:107695 TestOldCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:157696 int rv;
7697 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507698 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157699 } else {
[email protected]f3cf9802011-10-28 18:44:587700 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), &callback);
[email protected]044de0642010-06-17 10:42:157701 }
7702 if (rv == ERR_IO_PENDING)
7703 rv = callback.WaitForResult();
7704
7705 // Compare results with expected data.
7706 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507707 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157708 if (read_write_round.expected_rv == OK) {
[email protected]fe2255a2011-09-20 19:37:507709 ASSERT_TRUE(response != NULL);
[email protected]044de0642010-06-17 10:42:157710 } else {
7711 EXPECT_TRUE(response == NULL);
7712 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7713 continue;
7714 }
7715 if (round + 1 < test_config.num_auth_rounds) {
7716 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7717 } else {
7718 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7719 }
7720 }
[email protected]e5ae96a2010-04-14 20:12:457721 }
7722}
7723
[email protected]c871bce92010-07-15 21:51:147724TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7725 // Do multi-round authentication and make sure it works correctly.
7726 SessionDependencies session_deps;
7727 HttpAuthHandlerMock::Factory* auth_factory(
7728 new HttpAuthHandlerMock::Factory());
7729 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127730 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147731 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7732 session_deps.host_resolver->set_synchronous_mode(true);
7733
7734 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7735 auth_handler->set_connection_based(true);
7736 std::string auth_challenge = "Mock realm=server";
7737 GURL origin("http://www.example.com");
7738 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7739 auth_challenge.end());
7740 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7741 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087742 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147743
[email protected]c871bce92010-07-15 21:51:147744 int rv = OK;
7745 const HttpResponseInfo* response = NULL;
7746 HttpRequestInfo request;
7747 request.method = "GET";
7748 request.url = origin;
7749 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277750
7751 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107752
7753 // Use a TCP Socket Pool with only one connection per group. This is used
7754 // to validate that the TCP socket is not released to the pool between
7755 // each round of multi-round authentication.
7756 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287757 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7758 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107759 50, // Max sockets for pool
7760 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287761 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107762 session_deps.host_resolver.get(),
7763 &session_deps.socket_factory,
7764 session_deps.net_log);
[email protected]ab739042011-04-07 15:22:287765 session_peer.SetTransportSocketPool(transport_pool);
[email protected]7ef4cbbb2011-02-06 11:19:107766
[email protected]cb9bf6ca2011-01-28 13:15:277767 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:107768 TestOldCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:147769
7770 const MockWrite kGet(
7771 "GET / HTTP/1.1\r\n"
7772 "Host: www.example.com\r\n"
7773 "Connection: keep-alive\r\n\r\n");
7774 const MockWrite kGetAuth(
7775 "GET / HTTP/1.1\r\n"
7776 "Host: www.example.com\r\n"
7777 "Connection: keep-alive\r\n"
7778 "Authorization: auth_token\r\n\r\n");
7779
7780 const MockRead kServerChallenge(
7781 "HTTP/1.1 401 Unauthorized\r\n"
7782 "WWW-Authenticate: Mock realm=server\r\n"
7783 "Content-Type: text/html; charset=iso-8859-1\r\n"
7784 "Content-Length: 14\r\n\r\n"
7785 "Unauthorized\r\n");
7786 const MockRead kSuccess(
7787 "HTTP/1.1 200 OK\r\n"
7788 "Content-Type: text/html; charset=iso-8859-1\r\n"
7789 "Content-Length: 3\r\n\r\n"
7790 "Yes");
7791
7792 MockWrite writes[] = {
7793 // First round
7794 kGet,
7795 // Second round
7796 kGetAuth,
7797 // Third round
7798 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307799 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107800 kGetAuth,
7801 // Competing request
7802 kGet,
[email protected]c871bce92010-07-15 21:51:147803 };
7804 MockRead reads[] = {
7805 // First round
7806 kServerChallenge,
7807 // Second round
7808 kServerChallenge,
7809 // Third round
[email protected]eca50e122010-09-11 14:03:307810 kServerChallenge,
7811 // Fourth round
[email protected]c871bce92010-07-15 21:51:147812 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107813 // Competing response
7814 kSuccess,
[email protected]c871bce92010-07-15 21:51:147815 };
7816 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7817 writes, arraysize(writes));
7818 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7819
[email protected]7ef4cbbb2011-02-06 11:19:107820 const char* const kSocketGroup = "www.example.com:80";
7821
7822 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147823 auth_handler->SetGenerateExpectation(false, OK);
7824 rv = trans->Start(&request, &callback, BoundNetLog());
7825 if (rv == ERR_IO_PENDING)
7826 rv = callback.WaitForResult();
7827 EXPECT_EQ(OK, rv);
7828 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507829 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147830 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287831 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147832
[email protected]7ef4cbbb2011-02-06 11:19:107833 // In between rounds, another request comes in for the same domain.
7834 // It should not be able to grab the TCP socket that trans has already
7835 // claimed.
7836 scoped_ptr<HttpTransaction> trans_compete(
7837 new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:107838 TestOldCompletionCallback callback_compete;
[email protected]7ef4cbbb2011-02-06 11:19:107839 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7840 EXPECT_EQ(ERR_IO_PENDING, rv);
7841 // callback_compete.WaitForResult at this point would stall forever,
7842 // since the HttpNetworkTransaction does not release the request back to
7843 // the pool until after authentication completes.
7844
7845 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147846 auth_handler->SetGenerateExpectation(false, OK);
[email protected]f3cf9802011-10-28 18:44:587847 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback);
[email protected]c871bce92010-07-15 21:51:147848 if (rv == ERR_IO_PENDING)
7849 rv = callback.WaitForResult();
7850 EXPECT_EQ(OK, rv);
7851 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507852 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147853 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287854 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147855
[email protected]7ef4cbbb2011-02-06 11:19:107856 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147857 auth_handler->SetGenerateExpectation(false, OK);
[email protected]f3cf9802011-10-28 18:44:587858 rv = trans->RestartWithAuth(AuthCredentials(), &callback);
[email protected]c871bce92010-07-15 21:51:147859 if (rv == ERR_IO_PENDING)
7860 rv = callback.WaitForResult();
7861 EXPECT_EQ(OK, rv);
7862 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507863 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147864 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287865 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307866
[email protected]7ef4cbbb2011-02-06 11:19:107867 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307868 auth_handler->SetGenerateExpectation(false, OK);
[email protected]f3cf9802011-10-28 18:44:587869 rv = trans->RestartWithAuth(AuthCredentials(), &callback);
[email protected]eca50e122010-09-11 14:03:307870 if (rv == ERR_IO_PENDING)
7871 rv = callback.WaitForResult();
7872 EXPECT_EQ(OK, rv);
7873 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507874 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:307875 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287876 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107877
7878 // Read the body since the fourth round was successful. This will also
7879 // release the socket back to the pool.
7880 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7881 rv = trans->Read(io_buf, io_buf->size(), &callback);
7882 if (rv == ERR_IO_PENDING)
7883 rv = callback.WaitForResult();
7884 EXPECT_EQ(3, rv);
7885 rv = trans->Read(io_buf, io_buf->size(), &callback);
7886 EXPECT_EQ(0, rv);
7887 // There are still 0 idle sockets, since the trans_compete transaction
7888 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287889 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107890
7891 // The competing request can now finish. Wait for the headers and then
7892 // read the body.
7893 rv = callback_compete.WaitForResult();
7894 EXPECT_EQ(OK, rv);
7895 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7896 if (rv == ERR_IO_PENDING)
7897 rv = callback.WaitForResult();
7898 EXPECT_EQ(3, rv);
7899 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7900 EXPECT_EQ(0, rv);
7901
7902 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287903 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147904}
7905
[email protected]aeaca1f2010-04-20 22:05:217906class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7907 public:
[email protected]06650c52010-06-03 00:49:177908 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217909 : fail_all_(fail_all) {
7910 }
7911
7912 virtual MockRead GetNextRead() {
7913 if (fail_all_)
7914 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7915
7916 return MockRead(false /* async */,
7917 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7918 }
7919
7920 virtual MockWriteResult OnWrite(const std::string& data) {
7921 return MockWriteResult(false /* async */, data.size());
7922 }
7923
7924 void Reset() {
7925 }
7926
7927 private:
7928 const bool fail_all_;
7929};
7930
7931// Test that we restart a connection when we see a decompression failure from
7932// the peer during the handshake. (In the real world we'll restart with SSLv3
7933// and we won't offer DEFLATE in that case.)
7934TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7935 HttpRequestInfo request;
7936 request.method = "GET";
7937 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7938 request.load_flags = 0;
7939
7940 SessionDependencies session_deps;
7941 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7942 false /* fail all reads */);
7943 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7944 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117945 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217946 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7947 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7948 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7949 session_deps.socket_factory.AddSSLSocketDataProvider(
7950 &ssl_socket_data_provider1);
7951 session_deps.socket_factory.AddSSLSocketDataProvider(
7952 &ssl_socket_data_provider2);
7953
[email protected]e60e47a2010-07-14 03:37:187954 // Work around http://crbug.com/37454
7955 StaticSocketDataProvider bug37454_connection;
7956 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7957 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7958
[email protected]aeaca1f2010-04-20 22:05:217959 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7960 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:107961 TestOldCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:217962
[email protected]5a1d7ca2010-04-28 20:12:277963 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217964 EXPECT_EQ(ERR_IO_PENDING, rv);
7965 EXPECT_EQ(OK, callback.WaitForResult());
7966
7967 const HttpResponseInfo* response = trans->GetResponseInfo();
7968 ASSERT_TRUE(response != NULL);
7969 ASSERT_TRUE(response->headers != NULL);
7970 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7971
7972 std::string response_data;
7973 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7974 EXPECT_EQ("ok.", response_data);
7975}
7976
7977// Test that we restart a connection if we get a decompression failure from the
7978// peer while reading the first bytes from the connection. This occurs when the
7979// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7980// in the handshake.
7981TEST_F(HttpNetworkTransactionTest,
7982 RestartAfterTLSDecompressionFailureWithFalseStart) {
7983 HttpRequestInfo request;
7984 request.method = "GET";
7985 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7986 request.load_flags = 0;
7987
7988 SessionDependencies session_deps;
7989 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7990 true /* fail all reads */);
7991 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7992 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7993 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7994 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7995 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7996 session_deps.socket_factory.AddSSLSocketDataProvider(
7997 &ssl_socket_data_provider1);
7998 session_deps.socket_factory.AddSSLSocketDataProvider(
7999 &ssl_socket_data_provider2);
8000
8001 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8002 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:108003 TestOldCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218004
[email protected]5a1d7ca2010-04-28 20:12:278005 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218006 EXPECT_EQ(ERR_IO_PENDING, rv);
8007 EXPECT_EQ(OK, callback.WaitForResult());
8008
8009 const HttpResponseInfo* response = trans->GetResponseInfo();
8010 ASSERT_TRUE(response != NULL);
8011 ASSERT_TRUE(response->headers != NULL);
8012 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8013
8014 std::string response_data;
8015 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8016 EXPECT_EQ("ok.", response_data);
8017}
8018
[email protected]65041fa2010-05-21 06:56:538019// This tests the case that a request is issued via http instead of spdy after
8020// npn is negotiated.
8021TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:388022 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348023 HttpStreamFactory::set_next_protos(
8024 MakeNextProtos("http/1.1", "http1.1", NULL));
[email protected]65041fa2010-05-21 06:56:538025 SessionDependencies session_deps;
8026 HttpRequestInfo request;
8027 request.method = "GET";
8028 request.url = GURL("https://www.google.com/");
8029 request.load_flags = 0;
8030
8031 MockWrite data_writes[] = {
8032 MockWrite("GET / HTTP/1.1\r\n"
8033 "Host: www.google.com\r\n"
8034 "Connection: keep-alive\r\n\r\n"),
8035 };
8036
8037 MockRead data_reads[] = {
8038 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:358039 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:538040 MockRead("hello world"),
8041 MockRead(false, OK),
8042 };
8043
8044 SSLSocketDataProvider ssl(true, OK);
8045 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8046 ssl.next_proto = "http/1.1";
8047
8048 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8049
8050 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8051 data_writes, arraysize(data_writes));
8052 session_deps.socket_factory.AddSocketDataProvider(&data);
8053
[email protected]f1f3f0f82011-10-01 20:38:108054 TestOldCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:538055
8056 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8057 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8058
8059 int rv = trans->Start(&request, &callback, BoundNetLog());
8060
8061 EXPECT_EQ(ERR_IO_PENDING, rv);
8062 EXPECT_EQ(OK, callback.WaitForResult());
8063
8064 const HttpResponseInfo* response = trans->GetResponseInfo();
8065 ASSERT_TRUE(response != NULL);
8066 ASSERT_TRUE(response->headers != NULL);
8067 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8068
8069 std::string response_data;
8070 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8071 EXPECT_EQ("hello world", response_data);
8072
8073 EXPECT_FALSE(response->was_fetched_via_spdy);
8074 EXPECT_TRUE(response->was_npn_negotiated);
8075
[email protected]5285d972011-10-18 18:56:348076 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388077 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:538078}
[email protected]26ef6582010-06-24 02:30:478079
8080TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8081 // Simulate the SSL handshake completing with an NPN negotiation
8082 // followed by an immediate server closing of the socket.
8083 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:388084 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348085 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]26ef6582010-06-24 02:30:478086 SessionDependencies session_deps;
8087
8088 HttpRequestInfo request;
8089 request.method = "GET";
8090 request.url = GURL("https://www.google.com/");
8091 request.load_flags = 0;
8092
8093 SSLSocketDataProvider ssl(true, OK);
8094 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:358095 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:478096 ssl.was_npn_negotiated = true;
8097 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8098
[email protected]2bd93022010-07-17 00:58:448099 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:138100 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:478101
8102 MockRead spdy_reads[] = {
8103 MockRead(false, 0, 0) // Not async - return 0 immediately.
8104 };
8105
8106 scoped_refptr<DelayedSocketData> spdy_data(
8107 new DelayedSocketData(
8108 0, // don't wait in this case, immediate hangup.
8109 spdy_reads, arraysize(spdy_reads),
8110 spdy_writes, arraysize(spdy_writes)));
8111 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8112
[email protected]f1f3f0f82011-10-01 20:38:108113 TestOldCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:478114
8115 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8116 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8117
8118 int rv = trans->Start(&request, &callback, BoundNetLog());
8119 EXPECT_EQ(ERR_IO_PENDING, rv);
8120 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8121
[email protected]5285d972011-10-18 18:56:348122 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388123 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:478124}
[email protected]65d34382010-07-01 18:12:268125
[email protected]f45c1ee2010-08-03 00:54:308126TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8127 // This test ensures that the URL passed into the proxy is upgraded
8128 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:388129 HttpStreamFactory::set_use_alternate_protocols(true);
8130 HttpStreamFactory::set_next_protos(
[email protected]5285d972011-10-18 18:56:348131 MakeNextProtos("http/1.1", "http1.1", "spdy/2", "spdy", NULL));
[email protected]f45c1ee2010-08-03 00:54:308132
[email protected]81cdfcd2010-10-16 00:49:008133 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:308134 HttpAuthHandlerMock::Factory* auth_factory =
8135 new HttpAuthHandlerMock::Factory();
8136 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
[email protected]2d01c262011-08-11 23:07:088137 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:308138 auth_factory->set_do_init_from_challenge(true);
8139 session_deps.http_auth_handler_factory.reset(auth_factory);
8140
8141 HttpRequestInfo request;
8142 request.method = "GET";
8143 request.url = GURL("http://www.google.com");
8144 request.load_flags = 0;
8145
8146 // First round goes unauthenticated through the proxy.
8147 MockWrite data_writes_1[] = {
8148 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8149 "Host: www.google.com\r\n"
8150 "Proxy-Connection: keep-alive\r\n"
8151 "\r\n"),
8152 };
8153 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:598154 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:308155 MockRead("HTTP/1.1 200 OK\r\n"
8156 "Alternate-Protocol: 443:npn-spdy/2\r\n"
8157 "Proxy-Connection: close\r\n"
8158 "\r\n"),
8159 };
8160 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8161 data_writes_1, arraysize(data_writes_1));
8162
8163 // Second round tries to tunnel to www.google.com due to the
8164 // Alternate-Protocol announcement in the first round. It fails due
8165 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:598166 // After the failure, a tunnel is established to www.google.com using
8167 // Proxy-Authorization headers. There is then a SPDY request round.
8168 //
8169 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8170 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8171 // does a Disconnect and Connect on the same socket, rather than trying
8172 // to obtain a new one.
8173 //
8174 // NOTE: Originally, the proxy response to the second CONNECT request
8175 // simply returned another 407 so the unit test could skip the SSL connection
8176 // establishment and SPDY framing issues. Alas, the
8177 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308178 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598179
[email protected]f45c1ee2010-08-03 00:54:308180 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8181 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8182 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8183
[email protected]394816e92010-08-03 07:38:598184 MockWrite data_writes_2[] = {
8185 // First connection attempt without Proxy-Authorization.
8186 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8187 "Host: www.google.com\r\n"
8188 "Proxy-Connection: keep-alive\r\n"
8189 "\r\n"),
8190
8191 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308192 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8193 "Host: www.google.com\r\n"
8194 "Proxy-Connection: keep-alive\r\n"
8195 "Proxy-Authorization: auth_token\r\n"
8196 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308197
[email protected]394816e92010-08-03 07:38:598198 // SPDY request
8199 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308200 };
[email protected]394816e92010-08-03 07:38:598201 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8202 "Proxy-Authenticate: Mock\r\n"
8203 "Proxy-Connection: close\r\n"
8204 "\r\n");
8205 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8206 MockRead data_reads_2[] = {
8207 // First connection attempt fails
8208 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8209 MockRead(true, kRejectConnectResponse,
8210 arraysize(kRejectConnectResponse) - 1, 1),
8211
8212 // Second connection attempt passes
8213 MockRead(true, kAcceptConnectResponse,
8214 arraysize(kAcceptConnectResponse) -1, 4),
8215
8216 // SPDY response
8217 CreateMockRead(*resp.get(), 6),
8218 CreateMockRead(*data.get(), 6),
8219 MockRead(true, 0, 0, 6),
8220 };
8221 scoped_refptr<OrderedSocketData> data_2(
8222 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8223 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308224
8225 SSLSocketDataProvider ssl(true, OK);
8226 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8227 ssl.next_proto = "spdy/2";
8228 ssl.was_npn_negotiated = true;
8229
[email protected]2d6728692011-03-12 01:39:558230 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8231 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8232 NULL, 0, NULL, 0);
8233 hanging_non_alternate_protocol_socket.set_connect_data(
8234 never_finishing_connect);
8235
[email protected]f45c1ee2010-08-03 00:54:308236 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598237 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308238 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558239 session_deps.socket_factory.AddSocketDataProvider(
8240 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308241 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8242
8243 // First round should work and provide the Alternate-Protocol state.
[email protected]f1f3f0f82011-10-01 20:38:108244 TestOldCompletionCallback callback_1;
[email protected]f45c1ee2010-08-03 00:54:308245 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8246 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8247 EXPECT_EQ(ERR_IO_PENDING, rv);
8248 EXPECT_EQ(OK, callback_1.WaitForResult());
8249
8250 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]f1f3f0f82011-10-01 20:38:108251 TestOldCompletionCallback callback_2;
[email protected]f45c1ee2010-08-03 00:54:308252 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8253 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8254 EXPECT_EQ(ERR_IO_PENDING, rv);
8255 EXPECT_EQ(OK, callback_2.WaitForResult());
8256 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508257 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:308258 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8259
8260 // Restart with auth. Tunnel should work and response received.
[email protected]f1f3f0f82011-10-01 20:38:108261 TestOldCompletionCallback callback_3;
[email protected]f3cf9802011-10-28 18:44:588262 rv = trans_2->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback_3);
[email protected]f45c1ee2010-08-03 00:54:308263 EXPECT_EQ(ERR_IO_PENDING, rv);
8264 EXPECT_EQ(OK, callback_3.WaitForResult());
8265
8266 // After all that work, these two lines (or actually, just the scheme) are
8267 // what this test is all about. Make sure it happens correctly.
8268 const GURL& request_url = auth_handler->request_url();
8269 EXPECT_EQ("https", request_url.scheme());
8270 EXPECT_EQ("www.google.com", request_url.host());
8271
[email protected]5285d972011-10-18 18:56:348272 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388273 HttpStreamFactory::set_use_alternate_protocols(false);
8274}
8275
8276// Test that if we cancel the transaction as the connection is completing, that
8277// everything tears down correctly.
8278TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8279 // Setup everything about the connection to complete synchronously, so that
8280 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8281 // for is the callback from the HttpStreamRequest.
8282 // Then cancel the transaction.
8283 // Verify that we don't crash.
8284 MockConnect mock_connect(false, OK);
8285 MockRead data_reads[] = {
8286 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8287 MockRead(false, "hello world"),
8288 MockRead(false, OK),
8289 };
8290
[email protected]8e6441ca2010-08-19 05:56:388291 HttpRequestInfo request;
8292 request.method = "GET";
8293 request.url = GURL("http://www.google.com/");
8294 request.load_flags = 0;
8295
[email protected]cb9bf6ca2011-01-28 13:15:278296 SessionDependencies session_deps;
8297 session_deps.host_resolver->set_synchronous_mode(true);
8298 scoped_ptr<HttpTransaction> trans(
8299 new HttpNetworkTransaction(CreateSession(&session_deps)));
8300
[email protected]8e6441ca2010-08-19 05:56:388301 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8302 data.set_connect_data(mock_connect);
8303 session_deps.socket_factory.AddSocketDataProvider(&data);
8304
[email protected]f1f3f0f82011-10-01 20:38:108305 TestOldCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:388306
8307 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8308 int rv = trans->Start(&request, &callback, log.bound());
8309 EXPECT_EQ(ERR_IO_PENDING, rv);
8310 trans.reset(); // Cancel the transaction here.
8311
8312 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308313}
8314
[email protected]76a505b2010-08-25 06:23:008315// Test a basic GET request through a proxy.
8316TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008317 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008318 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8319 session_deps.net_log = log.bound().net_log();
8320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8321
[email protected]76a505b2010-08-25 06:23:008322 HttpRequestInfo request;
8323 request.method = "GET";
8324 request.url = GURL("http://www.google.com/");
8325
8326 MockWrite data_writes1[] = {
8327 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8328 "Host: www.google.com\r\n"
8329 "Proxy-Connection: keep-alive\r\n\r\n"),
8330 };
8331
8332 MockRead data_reads1[] = {
8333 MockRead("HTTP/1.1 200 OK\r\n"),
8334 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8335 MockRead("Content-Length: 100\r\n\r\n"),
8336 MockRead(false, OK),
8337 };
8338
8339 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8340 data_writes1, arraysize(data_writes1));
8341 session_deps.socket_factory.AddSocketDataProvider(&data1);
8342
[email protected]f1f3f0f82011-10-01 20:38:108343 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008344
[email protected]0b0bf032010-09-21 18:08:508345 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8346
[email protected]76a505b2010-08-25 06:23:008347 int rv = trans->Start(&request, &callback1, log.bound());
8348 EXPECT_EQ(ERR_IO_PENDING, rv);
8349
8350 rv = callback1.WaitForResult();
8351 EXPECT_EQ(OK, rv);
8352
8353 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508354 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008355
8356 EXPECT_TRUE(response->headers->IsKeepAlive());
8357 EXPECT_EQ(200, response->headers->response_code());
8358 EXPECT_EQ(100, response->headers->GetContentLength());
8359 EXPECT_TRUE(response->was_fetched_via_proxy);
8360 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8361}
8362
8363// Test a basic HTTPS GET request through a proxy.
8364TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008365 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008366 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8367 session_deps.net_log = log.bound().net_log();
8368 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8369
[email protected]76a505b2010-08-25 06:23:008370 HttpRequestInfo request;
8371 request.method = "GET";
8372 request.url = GURL("https://www.google.com/");
8373
8374 // Since we have proxy, should try to establish tunnel.
8375 MockWrite data_writes1[] = {
8376 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8377 "Host: www.google.com\r\n"
8378 "Proxy-Connection: keep-alive\r\n\r\n"),
8379
8380 MockWrite("GET / HTTP/1.1\r\n"
8381 "Host: www.google.com\r\n"
8382 "Connection: keep-alive\r\n\r\n"),
8383 };
8384
8385 MockRead data_reads1[] = {
8386 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8387
8388 MockRead("HTTP/1.1 200 OK\r\n"),
8389 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8390 MockRead("Content-Length: 100\r\n\r\n"),
8391 MockRead(false, OK),
8392 };
8393
8394 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8395 data_writes1, arraysize(data_writes1));
8396 session_deps.socket_factory.AddSocketDataProvider(&data1);
8397 SSLSocketDataProvider ssl(true, OK);
8398 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8399
[email protected]f1f3f0f82011-10-01 20:38:108400 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008401
[email protected]0b0bf032010-09-21 18:08:508402 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8403
[email protected]76a505b2010-08-25 06:23:008404 int rv = trans->Start(&request, &callback1, log.bound());
8405 EXPECT_EQ(ERR_IO_PENDING, rv);
8406
8407 rv = callback1.WaitForResult();
8408 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408409 net::CapturingNetLog::EntryList entries;
8410 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008411 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408412 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008413 NetLog::PHASE_NONE);
8414 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408415 entries, pos,
[email protected]76a505b2010-08-25 06:23:008416 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8417 NetLog::PHASE_NONE);
8418
8419 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508420 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008421
8422 EXPECT_TRUE(response->headers->IsKeepAlive());
8423 EXPECT_EQ(200, response->headers->response_code());
8424 EXPECT_EQ(100, response->headers->GetContentLength());
8425 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8426 EXPECT_TRUE(response->was_fetched_via_proxy);
8427}
8428
8429// Test a basic HTTPS GET request through a proxy, but the server hangs up
8430// while establishing the tunnel.
8431TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008432 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008433 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8434 session_deps.net_log = log.bound().net_log();
8435 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8436
[email protected]76a505b2010-08-25 06:23:008437 HttpRequestInfo request;
8438 request.method = "GET";
8439 request.url = GURL("https://www.google.com/");
8440
8441 // Since we have proxy, should try to establish tunnel.
8442 MockWrite data_writes1[] = {
8443 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8444 "Host: www.google.com\r\n"
8445 "Proxy-Connection: keep-alive\r\n\r\n"),
8446
8447 MockWrite("GET / HTTP/1.1\r\n"
8448 "Host: www.google.com\r\n"
8449 "Connection: keep-alive\r\n\r\n"),
8450 };
8451
8452 MockRead data_reads1[] = {
8453 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8454 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8455 MockRead(true, 0, 0), // EOF
8456 };
8457
8458 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8459 data_writes1, arraysize(data_writes1));
8460 session_deps.socket_factory.AddSocketDataProvider(&data1);
8461 SSLSocketDataProvider ssl(true, OK);
8462 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8463
[email protected]f1f3f0f82011-10-01 20:38:108464 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008465
[email protected]0b0bf032010-09-21 18:08:508466 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8467
[email protected]76a505b2010-08-25 06:23:008468 int rv = trans->Start(&request, &callback1, log.bound());
8469 EXPECT_EQ(ERR_IO_PENDING, rv);
8470
8471 rv = callback1.WaitForResult();
8472 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408473 net::CapturingNetLog::EntryList entries;
8474 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008475 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408476 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008477 NetLog::PHASE_NONE);
8478 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408479 entries, pos,
[email protected]76a505b2010-08-25 06:23:008480 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8481 NetLog::PHASE_NONE);
8482}
8483
[email protected]749eefa82010-09-13 22:14:038484// Test for crbug.com/55424.
8485TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8486 SessionDependencies session_deps;
8487
8488 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8489 "https://www.google.com", false, 1, LOWEST));
8490 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8491
8492 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8493 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8494 MockRead spdy_reads[] = {
8495 CreateMockRead(*resp),
8496 CreateMockRead(*data),
8497 MockRead(true, 0, 0),
8498 };
8499
8500 scoped_refptr<DelayedSocketData> spdy_data(
8501 new DelayedSocketData(
8502 1, // wait for one write to finish before reading.
8503 spdy_reads, arraysize(spdy_reads),
8504 spdy_writes, arraysize(spdy_writes)));
8505 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8506
8507 SSLSocketDataProvider ssl(true, OK);
8508 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8509 ssl.next_proto = "spdy/2";
8510 ssl.was_npn_negotiated = true;
8511 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8512
8513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8514
8515 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388516 HostPortPair host_port_pair("www.google.com", 443);
8517 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038518 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318519 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288520 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:298521 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]f1f3f0f82011-10-01 20:38:108522 TestOldCompletionCallback callback;
[email protected]02b0c342010-09-25 21:09:388523
8524 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8525 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288526 connection->Init(host_port_pair.ToString(), transport_params,
8527 LOWEST, &callback,
8528 session->transport_socket_pool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388529 EXPECT_EQ(OK, callback.WaitForResult());
8530 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038531
8532 HttpRequestInfo request;
8533 request.method = "GET";
8534 request.url = GURL("https://www.google.com/");
8535 request.load_flags = 0;
8536
8537 // This is the important line that marks this as a preconnect.
8538 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8539
8540 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8541
[email protected]749eefa82010-09-13 22:14:038542 int rv = trans->Start(&request, &callback, BoundNetLog());
8543 EXPECT_EQ(ERR_IO_PENDING, rv);
8544 EXPECT_EQ(OK, callback.WaitForResult());
8545}
8546
[email protected]73b8dd222010-11-11 19:55:248547// Given a net error, cause that error to be returned from the first Write()
8548// call and verify that the HttpTransaction fails with that error.
8549static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278550 net::HttpRequestInfo request_info;
8551 request_info.url = GURL("https://www.example.com/");
8552 request_info.method = "GET";
8553 request_info.load_flags = net::LOAD_NORMAL;
8554
[email protected]73b8dd222010-11-11 19:55:248555 SessionDependencies session_deps;
8556
8557 SSLSocketDataProvider ssl_data(async, OK);
8558 net::MockWrite data_writes[] = {
8559 net::MockWrite(async, error),
8560 };
8561 net::StaticSocketDataProvider data(NULL, 0,
8562 data_writes, arraysize(data_writes));
8563 session_deps.socket_factory.AddSocketDataProvider(&data);
8564 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8565
8566 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8567 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8568
[email protected]f1f3f0f82011-10-01 20:38:108569 TestOldCompletionCallback callback;
[email protected]73b8dd222010-11-11 19:55:248570 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8571 if (rv == net::ERR_IO_PENDING)
8572 rv = callback.WaitForResult();
8573 ASSERT_EQ(error, rv);
8574}
8575
8576TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8577 // Just check a grab bag of cert errors.
8578 static const int kErrors[] = {
8579 ERR_CERT_COMMON_NAME_INVALID,
8580 ERR_CERT_AUTHORITY_INVALID,
8581 ERR_CERT_DATE_INVALID,
8582 };
8583 for (size_t i = 0; i < arraysize(kErrors); i++) {
8584 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8585 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8586 }
8587}
8588
[email protected]bd0b6772011-01-11 19:59:308589// Ensure that a client certificate is removed from the SSL client auth
8590// cache when:
8591// 1) No proxy is involved.
8592// 2) TLS False Start is disabled.
8593// 3) The initial TLS handshake requests a client certificate.
8594// 4) The client supplies an invalid/unacceptable certificate.
8595TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278596 net::HttpRequestInfo request_info;
8597 request_info.url = GURL("https://www.example.com/");
8598 request_info.method = "GET";
8599 request_info.load_flags = net::LOAD_NORMAL;
8600
[email protected]bd0b6772011-01-11 19:59:308601 SessionDependencies session_deps;
8602
8603 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8604 cert_request->host_and_port = "www.example.com:443";
8605
8606 // [ssl_]data1 contains the data for the first SSL handshake. When a
8607 // CertificateRequest is received for the first time, the handshake will
8608 // be aborted to allow the caller to provide a certificate.
8609 SSLSocketDataProvider ssl_data1(true /* async */,
8610 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8611 ssl_data1.cert_request_info = cert_request.get();
8612 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8613 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8614 session_deps.socket_factory.AddSocketDataProvider(&data1);
8615
8616 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8617 // False Start is not being used, the result of the SSL handshake will be
8618 // returned as part of the SSLClientSocket::Connect() call. This test
8619 // matches the result of a server sending a handshake_failure alert,
8620 // rather than a Finished message, because it requires a client
8621 // certificate and none was supplied.
8622 SSLSocketDataProvider ssl_data2(true /* async */,
8623 net::ERR_SSL_PROTOCOL_ERROR);
8624 ssl_data2.cert_request_info = cert_request.get();
8625 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8626 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8627 session_deps.socket_factory.AddSocketDataProvider(&data2);
8628
8629 // [ssl_]data3 contains the data for the third SSL handshake. When a
8630 // connection to a server fails during an SSL handshake,
8631 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8632 // connection was attempted with TLSv1. This is transparent to the caller
8633 // of the HttpNetworkTransaction. Because this test failure is due to
8634 // requiring a client certificate, this fallback handshake should also
8635 // fail.
8636 SSLSocketDataProvider ssl_data3(true /* async */,
8637 net::ERR_SSL_PROTOCOL_ERROR);
8638 ssl_data3.cert_request_info = cert_request.get();
8639 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8640 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8641 session_deps.socket_factory.AddSocketDataProvider(&data3);
8642
8643 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8644 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8645
[email protected]bd0b6772011-01-11 19:59:308646 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]f1f3f0f82011-10-01 20:38:108647 TestOldCompletionCallback callback;
[email protected]bd0b6772011-01-11 19:59:308648 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8649 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8650
8651 // Complete the SSL handshake, which should abort due to requiring a
8652 // client certificate.
8653 rv = callback.WaitForResult();
8654 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8655
8656 // Indicate that no certificate should be supplied. From the perspective
8657 // of SSLClientCertCache, NULL is just as meaningful as a real
8658 // certificate, so this is the same as supply a
8659 // legitimate-but-unacceptable certificate.
8660 rv = trans->RestartWithCertificate(NULL, &callback);
8661 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8662
8663 // Ensure the certificate was added to the client auth cache before
8664 // allowing the connection to continue restarting.
8665 scoped_refptr<X509Certificate> client_cert;
8666 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8667 &client_cert));
8668 ASSERT_EQ(NULL, client_cert.get());
8669
8670 // Restart the handshake. This will consume ssl_data2, which fails, and
8671 // then consume ssl_data3, which should also fail. The result code is
8672 // checked against what ssl_data3 should return.
8673 rv = callback.WaitForResult();
8674 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8675
8676 // Ensure that the client certificate is removed from the cache on a
8677 // handshake failure.
8678 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8679 &client_cert));
8680}
8681
8682// Ensure that a client certificate is removed from the SSL client auth
8683// cache when:
8684// 1) No proxy is involved.
8685// 2) TLS False Start is enabled.
8686// 3) The initial TLS handshake requests a client certificate.
8687// 4) The client supplies an invalid/unacceptable certificate.
8688TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278689 net::HttpRequestInfo request_info;
8690 request_info.url = GURL("https://www.example.com/");
8691 request_info.method = "GET";
8692 request_info.load_flags = net::LOAD_NORMAL;
8693
[email protected]bd0b6772011-01-11 19:59:308694 SessionDependencies session_deps;
8695
8696 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8697 cert_request->host_and_port = "www.example.com:443";
8698
8699 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8700 // return successfully after reading up to the peer's Certificate message.
8701 // This is to allow the caller to call SSLClientSocket::Write(), which can
8702 // enqueue application data to be sent in the same packet as the
8703 // ChangeCipherSpec and Finished messages.
8704 // The actual handshake will be finished when SSLClientSocket::Read() is
8705 // called, which expects to process the peer's ChangeCipherSpec and
8706 // Finished messages. If there was an error negotiating with the peer,
8707 // such as due to the peer requiring a client certificate when none was
8708 // supplied, the alert sent by the peer won't be processed until Read() is
8709 // called.
8710
8711 // Like the non-False Start case, when a client certificate is requested by
8712 // the peer, the handshake is aborted during the Connect() call.
8713 // [ssl_]data1 represents the initial SSL handshake with the peer.
8714 SSLSocketDataProvider ssl_data1(true /* async */,
8715 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8716 ssl_data1.cert_request_info = cert_request.get();
8717 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8718 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8719 session_deps.socket_factory.AddSocketDataProvider(&data1);
8720
8721 // When a client certificate is supplied, Connect() will not be aborted
8722 // when the peer requests the certificate. Instead, the handshake will
8723 // artificially succeed, allowing the caller to write the HTTP request to
8724 // the socket. The handshake messages are not processed until Read() is
8725 // called, which then detects that the handshake was aborted, due to the
8726 // peer sending a handshake_failure because it requires a client
8727 // certificate.
8728 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8729 ssl_data2.cert_request_info = cert_request.get();
8730 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8731 net::MockRead data2_reads[] = {
8732 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8733 };
8734 net::StaticSocketDataProvider data2(
8735 data2_reads, arraysize(data2_reads), NULL, 0);
8736 session_deps.socket_factory.AddSocketDataProvider(&data2);
8737
8738 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8739 // the data for the SSL handshake once the TLSv1 connection falls back to
8740 // SSLv3. It has the same behaviour as [ssl_]data2.
8741 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8742 ssl_data3.cert_request_info = cert_request.get();
8743 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8744 net::StaticSocketDataProvider data3(
8745 data2_reads, arraysize(data2_reads), NULL, 0);
8746 session_deps.socket_factory.AddSocketDataProvider(&data3);
8747
8748 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8749 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8750
[email protected]bd0b6772011-01-11 19:59:308751 // Begin the initial SSL handshake.
[email protected]f1f3f0f82011-10-01 20:38:108752 TestOldCompletionCallback callback;
[email protected]bd0b6772011-01-11 19:59:308753 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8754 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8755
8756 // Complete the SSL handshake, which should abort due to requiring a
8757 // client certificate.
8758 rv = callback.WaitForResult();
8759 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8760
8761 // Indicate that no certificate should be supplied. From the perspective
8762 // of SSLClientCertCache, NULL is just as meaningful as a real
8763 // certificate, so this is the same as supply a
8764 // legitimate-but-unacceptable certificate.
8765 rv = trans->RestartWithCertificate(NULL, &callback);
8766 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8767
8768 // Ensure the certificate was added to the client auth cache before
8769 // allowing the connection to continue restarting.
8770 scoped_refptr<X509Certificate> client_cert;
8771 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8772 &client_cert));
8773 ASSERT_EQ(NULL, client_cert.get());
8774
8775
8776 // Restart the handshake. This will consume ssl_data2, which fails, and
8777 // then consume ssl_data3, which should also fail. The result code is
8778 // checked against what ssl_data3 should return.
8779 rv = callback.WaitForResult();
8780 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8781
8782 // Ensure that the client certificate is removed from the cache on a
8783 // handshake failure.
8784 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8785 &client_cert));
8786}
8787
[email protected]8c405132011-01-11 22:03:188788// Ensure that a client certificate is removed from the SSL client auth
8789// cache when:
8790// 1) An HTTPS proxy is involved.
8791// 3) The HTTPS proxy requests a client certificate.
8792// 4) The client supplies an invalid/unacceptable certificate for the
8793// proxy.
8794// The test is repeated twice, first for connecting to an HTTPS endpoint,
8795// then for connecting to an HTTP endpoint.
8796TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8797 SessionDependencies session_deps(
8798 ProxyService::CreateFixed("https://proxy:70"));
8799 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8800 session_deps.net_log = log.bound().net_log();
8801
8802 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8803 cert_request->host_and_port = "proxy:70";
8804
8805 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8806 // [ssl_]data[1-3]. Rather than represending the endpoint
8807 // (www.example.com:443), they represent failures with the HTTPS proxy
8808 // (proxy:70).
8809 SSLSocketDataProvider ssl_data1(true /* async */,
8810 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8811 ssl_data1.cert_request_info = cert_request.get();
8812 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8813 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8814 session_deps.socket_factory.AddSocketDataProvider(&data1);
8815
8816 SSLSocketDataProvider ssl_data2(true /* async */,
8817 net::ERR_SSL_PROTOCOL_ERROR);
8818 ssl_data2.cert_request_info = cert_request.get();
8819 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8820 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8821 session_deps.socket_factory.AddSocketDataProvider(&data2);
8822
8823 SSLSocketDataProvider ssl_data3(true /* async */,
8824 net::ERR_SSL_PROTOCOL_ERROR);
8825 ssl_data3.cert_request_info = cert_request.get();
8826 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8827 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8828 session_deps.socket_factory.AddSocketDataProvider(&data3);
8829
8830 net::HttpRequestInfo requests[2];
8831 requests[0].url = GURL("https://www.example.com/");
8832 requests[0].method = "GET";
8833 requests[0].load_flags = net::LOAD_NORMAL;
8834
8835 requests[1].url = GURL("http://www.example.com/");
8836 requests[1].method = "GET";
8837 requests[1].load_flags = net::LOAD_NORMAL;
8838
8839 for (size_t i = 0; i < arraysize(requests); ++i) {
8840 session_deps.socket_factory.ResetNextMockIndexes();
8841 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8842 scoped_ptr<HttpNetworkTransaction> trans(
8843 new HttpNetworkTransaction(session));
8844
8845 // Begin the SSL handshake with the proxy.
[email protected]f1f3f0f82011-10-01 20:38:108846 TestOldCompletionCallback callback;
[email protected]8c405132011-01-11 22:03:188847 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8848 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8849
8850 // Complete the SSL handshake, which should abort due to requiring a
8851 // client certificate.
8852 rv = callback.WaitForResult();
8853 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8854
8855 // Indicate that no certificate should be supplied. From the perspective
8856 // of SSLClientCertCache, NULL is just as meaningful as a real
8857 // certificate, so this is the same as supply a
8858 // legitimate-but-unacceptable certificate.
8859 rv = trans->RestartWithCertificate(NULL, &callback);
8860 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8861
8862 // Ensure the certificate was added to the client auth cache before
8863 // allowing the connection to continue restarting.
8864 scoped_refptr<X509Certificate> client_cert;
8865 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8866 &client_cert));
8867 ASSERT_EQ(NULL, client_cert.get());
8868 // Ensure the certificate was NOT cached for the endpoint. This only
8869 // applies to HTTPS requests, but is fine to check for HTTP requests.
8870 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8871 &client_cert));
8872
8873 // Restart the handshake. This will consume ssl_data2, which fails, and
8874 // then consume ssl_data3, which should also fail. The result code is
8875 // checked against what ssl_data3 should return.
8876 rv = callback.WaitForResult();
8877 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8878
8879 // Now that the new handshake has failed, ensure that the client
8880 // certificate was removed from the client auth cache.
8881 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8882 &client_cert));
8883 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8884 &client_cert));
8885 }
8886}
8887
[email protected]5c288bc2011-07-26 15:12:058888void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8889 SpdySessionPoolPeer* pool_peer,
8890 std::string host,
8891 int port,
8892 std::string iplist) {
8893 // Create a host resolver dependency that returns address |iplist| for
8894 // resolutions of |host|.
8895 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:048896
[email protected]5c288bc2011-07-26 15:12:058897 // Setup a HostPortProxyPair.
8898 HostPortPair host_port_pair(host, port);
8899 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
8900 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:048901
[email protected]5c288bc2011-07-26 15:12:058902 // Resolve the host and port.
8903 AddressList addresses;
8904 HostResolver::RequestInfo info(host_port_pair);
[email protected]aa22b242011-11-16 18:58:298905 TestCompletionCallback callback;
8906 int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:478907 BoundNetLog());
8908 if (rv == ERR_IO_PENDING)
8909 rv = callback.WaitForResult();
8910 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:048911
[email protected]5c288bc2011-07-26 15:12:058912 // Add the first address as an alias. It would have been better to call
8913 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
8914 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
8915 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
8916 // the |pair|.
8917 const addrinfo* address = addresses.head();
8918 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:048919}
8920
[email protected]e3ceb682011-06-28 23:55:468921TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
8922 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348923 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:468924
8925 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
8926 SessionDependencies session_deps;
8927 MockCachingHostResolver host_resolver;
8928 net::HttpNetworkSession::Params params;
8929 params.client_socket_factory = &session_deps.socket_factory;
8930 params.host_resolver = &host_resolver;
8931 params.cert_verifier = session_deps.cert_verifier.get();
8932 params.proxy_service = session_deps.proxy_service.get();
8933 params.ssl_config_service = session_deps.ssl_config_service;
8934 params.http_auth_handler_factory =
8935 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:538936 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:468937 params.net_log = session_deps.net_log;
8938 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268939 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8940 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468941
8942 SSLSocketDataProvider ssl(true, OK);
8943 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8944 ssl.next_proto = "spdy/2";
8945 ssl.was_npn_negotiated = true;
8946 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8947
8948 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8949 "https://www.google.com", false, 1, LOWEST));
8950 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8951 "https://www.gmail.com", false, 3, LOWEST));
8952 MockWrite spdy_writes[] = {
8953 CreateMockWrite(*host1_req, 1),
8954 CreateMockWrite(*host2_req, 4),
8955 };
8956 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8957 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8958 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8959 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8960 MockRead spdy_reads[] = {
8961 CreateMockRead(*host1_resp, 2),
8962 CreateMockRead(*host1_resp_body, 3),
8963 CreateMockRead(*host2_resp, 5),
8964 CreateMockRead(*host2_resp_body, 6),
8965 MockRead(true, 0, 7),
8966 };
8967
8968 scoped_refptr<OrderedSocketData> spdy_data(
8969 new OrderedSocketData(
8970 spdy_reads, arraysize(spdy_reads),
8971 spdy_writes, arraysize(spdy_writes)));
8972 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8973
[email protected]aa22b242011-11-16 18:58:298974 TestCompletionCallback callback;
8975 TestOldCompletionCallback old_callback;
[email protected]e3ceb682011-06-28 23:55:468976 HttpRequestInfo request1;
8977 request1.method = "GET";
8978 request1.url = GURL("https://www.google.com/");
8979 request1.load_flags = 0;
8980 HttpNetworkTransaction trans1(session);
8981
[email protected]aa22b242011-11-16 18:58:298982 int rv = trans1.Start(&request1, &old_callback, BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:468983 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]aa22b242011-11-16 18:58:298984 EXPECT_EQ(OK, old_callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:468985
8986 const HttpResponseInfo* response = trans1.GetResponseInfo();
8987 ASSERT_TRUE(response != NULL);
8988 ASSERT_TRUE(response->headers != NULL);
8989 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8990
8991 std::string response_data;
8992 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8993 EXPECT_EQ("hello!", response_data);
8994
8995 // Preload www.gmail.com into HostCache.
8996 HostPortPair host_port("www.gmail.com", 443);
8997 HostResolver::RequestInfo resolve_info(host_port);
8998 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:298999 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479000 BoundNetLog());
9001 EXPECT_EQ(ERR_IO_PENDING, rv);
9002 rv = callback.WaitForResult();
9003 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469004
[email protected]5c288bc2011-07-26 15:12:059005 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9006 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9007 // (www.google.com, 443).
9008 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
9009 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049010
[email protected]e3ceb682011-06-28 23:55:469011 HttpRequestInfo request2;
9012 request2.method = "GET";
9013 request2.url = GURL("https://www.gmail.com/");
9014 request2.load_flags = 0;
9015 HttpNetworkTransaction trans2(session);
9016
[email protected]aa22b242011-11-16 18:58:299017 rv = trans2.Start(&request2, &old_callback, BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469018 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]aa22b242011-11-16 18:58:299019 EXPECT_EQ(OK, old_callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469020
9021 response = trans2.GetResponseInfo();
9022 ASSERT_TRUE(response != NULL);
9023 ASSERT_TRUE(response->headers != NULL);
9024 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9025 EXPECT_TRUE(response->was_fetched_via_spdy);
9026 EXPECT_TRUE(response->was_npn_negotiated);
9027 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9028 EXPECT_EQ("hello!", response_data);
9029
[email protected]5285d972011-10-18 18:56:349030 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469031 HttpStreamFactory::set_use_alternate_protocols(false);
9032}
9033
9034class OneTimeCachingHostResolver : public net::HostResolver {
9035 public:
9036 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9037 : host_port_(host_port) {}
9038 virtual ~OneTimeCachingHostResolver() {}
9039
9040 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9041
9042 // HostResolver methods:
9043 virtual int Resolve(const RequestInfo& info,
9044 AddressList* addresses,
[email protected]aa22b242011-11-16 18:58:299045 const CompletionCallback& callback,
[email protected]e3ceb682011-06-28 23:55:469046 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:409047 const BoundNetLog& net_log) OVERRIDE {
9048 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:469049 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:409050 }
9051
9052 virtual int ResolveFromCache(const RequestInfo& info,
9053 AddressList* addresses,
9054 const BoundNetLog& net_log) OVERRIDE {
9055 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9056 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:099057 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:469058 return rv;
9059 }
9060
[email protected]95a214c2011-08-04 21:50:409061 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469062 host_resolver_.CancelRequest(req);
9063 }
9064
[email protected]46da33be2011-07-19 21:58:049065 MockCachingHostResolver* GetMockHostResolver() {
9066 return &host_resolver_;
9067 }
9068
[email protected]e3ceb682011-06-28 23:55:469069 private:
9070 MockCachingHostResolver host_resolver_;
9071 const HostPortPair host_port_;
9072};
9073
9074TEST_F(HttpNetworkTransactionTest,
9075 UseIPConnectionPoolingWithHostCacheExpiration) {
9076 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349077 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469078
9079 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9080 SessionDependencies session_deps;
9081 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9082 net::HttpNetworkSession::Params params;
9083 params.client_socket_factory = &session_deps.socket_factory;
9084 params.host_resolver = &host_resolver;
9085 params.cert_verifier = session_deps.cert_verifier.get();
9086 params.proxy_service = session_deps.proxy_service.get();
9087 params.ssl_config_service = session_deps.ssl_config_service;
9088 params.http_auth_handler_factory =
9089 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539090 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469091 params.net_log = session_deps.net_log;
9092 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269093 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9094 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469095
9096 SSLSocketDataProvider ssl(true, OK);
9097 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9098 ssl.next_proto = "spdy/2";
9099 ssl.was_npn_negotiated = true;
9100 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9101
9102 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9103 "https://www.google.com", false, 1, LOWEST));
9104 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9105 "https://www.gmail.com", false, 3, LOWEST));
9106 MockWrite spdy_writes[] = {
9107 CreateMockWrite(*host1_req, 1),
9108 CreateMockWrite(*host2_req, 4),
9109 };
9110 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9111 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9112 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9113 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9114 MockRead spdy_reads[] = {
9115 CreateMockRead(*host1_resp, 2),
9116 CreateMockRead(*host1_resp_body, 3),
9117 CreateMockRead(*host2_resp, 5),
9118 CreateMockRead(*host2_resp_body, 6),
9119 MockRead(true, 0, 7),
9120 };
9121
9122 scoped_refptr<OrderedSocketData> spdy_data(
9123 new OrderedSocketData(
9124 spdy_reads, arraysize(spdy_reads),
9125 spdy_writes, arraysize(spdy_writes)));
9126 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
9127
[email protected]aa22b242011-11-16 18:58:299128 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469129 HttpRequestInfo request1;
9130 request1.method = "GET";
9131 request1.url = GURL("https://www.google.com/");
9132 request1.load_flags = 0;
9133 HttpNetworkTransaction trans1(session);
9134
[email protected]aa22b242011-11-16 18:58:299135 TestOldCompletionCallback old_callback;
9136 int rv = trans1.Start(&request1, &old_callback, BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469137 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]aa22b242011-11-16 18:58:299138 EXPECT_EQ(OK, old_callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469139
9140 const HttpResponseInfo* response = trans1.GetResponseInfo();
9141 ASSERT_TRUE(response != NULL);
9142 ASSERT_TRUE(response->headers != NULL);
9143 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9144
9145 std::string response_data;
9146 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9147 EXPECT_EQ("hello!", response_data);
9148
9149 // Preload cache entries into HostCache.
9150 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9151 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299152 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479153 BoundNetLog());
9154 EXPECT_EQ(ERR_IO_PENDING, rv);
9155 rv = callback.WaitForResult();
9156 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469157
9158 HttpRequestInfo request2;
9159 request2.method = "GET";
9160 request2.url = GURL("https://www.gmail.com/");
9161 request2.load_flags = 0;
9162 HttpNetworkTransaction trans2(session);
9163
[email protected]5c288bc2011-07-26 15:12:059164 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9165 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9166 // (www.google.com, 443).
9167 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9168 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049169
[email protected]aa22b242011-11-16 18:58:299170 rv = trans2.Start(&request2, &old_callback, BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469171 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]aa22b242011-11-16 18:58:299172 EXPECT_EQ(OK, old_callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469173
9174 response = trans2.GetResponseInfo();
9175 ASSERT_TRUE(response != NULL);
9176 ASSERT_TRUE(response->headers != NULL);
9177 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9178 EXPECT_TRUE(response->was_fetched_via_spdy);
9179 EXPECT_TRUE(response->was_npn_negotiated);
9180 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9181 EXPECT_EQ("hello!", response_data);
9182
[email protected]5285d972011-10-18 18:56:349183 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469184 HttpStreamFactory::set_use_alternate_protocols(false);
9185}
9186
[email protected]5a60c8b2011-10-19 20:14:299187TEST_F(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
9188 MockRead data_reads1[] = {
9189 MockRead(false, ERR_PIPELINE_EVICTION),
9190 };
9191 MockRead data_reads2[] = {
9192 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9193 MockRead("hello world"),
9194 MockRead(false, OK),
9195 };
9196 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
9197 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
9198 StaticSocketDataProvider* data[] = { &data1, &data2 };
9199
9200 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9201
9202 EXPECT_EQ(OK, out.rv);
9203 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9204 EXPECT_EQ("hello world", out.response_data);
9205}
9206
9207TEST_F(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
9208 MockWrite data_writes1[] = {
9209 MockWrite(false, ERR_PIPELINE_EVICTION),
9210 };
9211 MockWrite data_writes2[] = {
9212 MockWrite("GET / HTTP/1.1\r\n"
9213 "Host: www.google.com\r\n"
9214 "Connection: keep-alive\r\n\r\n"),
9215 };
9216 MockRead data_reads2[] = {
9217 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9218 MockRead("hello world"),
9219 MockRead(false, OK),
9220 };
9221 StaticSocketDataProvider data1(NULL, 0,
9222 data_writes1, arraysize(data_writes1));
9223 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9224 data_writes2, arraysize(data_writes2));
9225 StaticSocketDataProvider* data[] = { &data1, &data2 };
9226
9227 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9228
9229 EXPECT_EQ(OK, out.rv);
9230 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9231 EXPECT_EQ("hello world", out.response_data);
9232}
9233
[email protected]89ceba9a2009-03-21 03:46:069234} // namespace net