blob: 7c02e83e8b5501b3d3c3b67dd5091730ff010839 [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]f3e6c1e2009-06-15 20:52:125797// Host resolution observer used by
5798// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5799// resovle requests are issued with a referrer of |expected_referrer|.
5800class ResolutionReferrerObserver : public HostResolver::Observer {
5801 public:
5802 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5803 : expected_referrer_(expected_referrer),
5804 called_start_with_referrer_(false),
5805 called_finish_with_referrer_(false) {
5806 }
5807
5808 virtual void OnStartResolution(int id,
5809 const HostResolver::RequestInfo& info) {
5810 if (info.referrer() == expected_referrer_)
5811 called_start_with_referrer_ = true;
5812 }
5813
5814 virtual void OnFinishResolutionWithStatus(
5815 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5816 if (info.referrer() == expected_referrer_)
5817 called_finish_with_referrer_ = true;
5818 }
5819
[email protected]eb255d32009-06-17 02:11:035820 virtual void OnCancelResolution(int id,
5821 const HostResolver::RequestInfo& info ) {
5822 FAIL() << "Should not be cancelling any requests!";
5823 }
5824
[email protected]f3e6c1e2009-06-15 20:52:125825 bool did_complete_with_expected_referrer() const {
5826 return called_start_with_referrer_ && called_finish_with_referrer_;
5827 }
5828
5829 private:
5830 GURL expected_referrer_;
5831 bool called_start_with_referrer_;
5832 bool called_finish_with_referrer_;
5833
5834 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5835};
5836
5837// Make sure that when HostResolver::Resolve() is invoked, it passes through
5838// the "referrer". This is depended on by the DNS prefetch observer.
5839TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5840 GURL referrer = GURL("http://expected-referrer/");
5841 EXPECT_TRUE(referrer.is_valid());
5842 ResolutionReferrerObserver resolution_observer(referrer);
5843
[email protected]cb9bf6ca2011-01-28 13:15:275844 // Issue a request, containing an HTTP referrer.
5845 HttpRequestInfo request;
5846 request.method = "GET";
[email protected]cb9bf6ca2011-01-28 13:15:275847 request.url = GURL("http://www.google.com/");
[email protected]c10450102011-06-27 09:06:165848 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5849 referrer.spec());
[email protected]cb9bf6ca2011-01-28 13:15:275850
[email protected]f3e6c1e2009-06-15 20:52:125851 SessionDependencies session_deps;
5852 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435853 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125854
5855 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145856 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125857
5858 // Connect up a mock socket which will fail when reading.
5859 MockRead data_reads[] = {
5860 MockRead(false, ERR_FAILED),
5861 };
[email protected]31a2bfe2010-02-09 08:03:395862 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595863 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125864
[email protected]f3e6c1e2009-06-15 20:52:125865 // Run the request until it fails reading from the socket.
[email protected]f1f3f0f82011-10-01 20:38:105866 TestOldCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275867 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125868 EXPECT_EQ(ERR_IO_PENDING, rv);
5869 rv = callback.WaitForResult();
5870 EXPECT_EQ(ERR_FAILED, rv);
5871
5872 // Check that the host resolution observer saw |referrer|.
5873 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5874}
5875
[email protected]685af592010-05-11 19:31:245876// Base test to make sure that when the load flags for a request specify to
5877// bypass the cache, the DNS cache is not used.
5878void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275879 // Issue a request, asking to bypass the cache(s).
5880 HttpRequestInfo request;
5881 request.method = "GET";
5882 request.load_flags = load_flags;
5883 request.url = GURL("http://www.google.com/");
5884
[email protected]3b9cca42009-06-16 01:08:285885 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325886
[email protected]a2c2fb92009-07-18 07:31:045887 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545888 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325889
[email protected]3b9cca42009-06-16 01:08:285890 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435891 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285892
[email protected]6e78dfb2011-07-28 21:34:475893 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285894 AddressList addrlist;
[email protected]f1f3f0f82011-10-01 20:38:105895 TestOldCompletionCallback callback;
[email protected]94a0d3d92009-06-27 01:50:145896 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105897 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]6e78dfb2011-07-28 21:34:475898 &callback, NULL, BoundNetLog());
5899 EXPECT_EQ(ERR_IO_PENDING, rv);
5900 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285901 EXPECT_EQ(OK, rv);
5902
5903 // Verify that it was added to host cache, by doing a subsequent async lookup
5904 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465905 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105906 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]6e78dfb2011-07-28 21:34:475907 &callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325908 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285909
5910 // Inject a failure the next time that "www.google.com" is resolved. This way
5911 // we can tell if the next lookup hit the cache, or the "network".
5912 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325913 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285914
5915 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5916 // first read -- this won't be reached as the host resolution will fail first.
5917 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395918 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595919 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285920
[email protected]3b9cca42009-06-16 01:08:285921 // Run the request.
[email protected]5a1d7ca2010-04-28 20:12:275922 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285923 ASSERT_EQ(ERR_IO_PENDING, rv);
5924 rv = callback.WaitForResult();
5925
5926 // If we bypassed the cache, we would have gotten a failure while resolving
5927 // "www.google.com".
5928 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5929}
5930
[email protected]685af592010-05-11 19:31:245931// There are multiple load flags that should trigger the host cache bypass.
5932// Test each in isolation:
5933TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5934 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5935}
5936
5937TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5938 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5939}
5940
5941TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5942 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5943}
5944
[email protected]0877e3d2009-10-17 22:29:575945// Make sure we can handle an error when writing the request.
5946TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5947 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275948 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575949
5950 HttpRequestInfo request;
5951 request.method = "GET";
5952 request.url = GURL("http://www.foo.com/");
5953 request.load_flags = 0;
5954
5955 MockWrite write_failure[] = {
5956 MockWrite(true, ERR_CONNECTION_RESET),
5957 };
[email protected]31a2bfe2010-02-09 08:03:395958 StaticSocketDataProvider data(NULL, 0,
5959 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595960 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575961
[email protected]f1f3f0f82011-10-01 20:38:105962 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575963
5964 scoped_ptr<HttpTransaction> trans(
5965 new HttpNetworkTransaction(CreateSession(&session_deps)));
5966
[email protected]5a1d7ca2010-04-28 20:12:275967 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575968 EXPECT_EQ(ERR_IO_PENDING, rv);
5969
5970 rv = callback.WaitForResult();
5971 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5972}
5973
5974// Check that a connection closed after the start of the headers finishes ok.
5975TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5976 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275977 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575978
5979 HttpRequestInfo request;
5980 request.method = "GET";
5981 request.url = GURL("http://www.foo.com/");
5982 request.load_flags = 0;
5983
5984 MockRead data_reads[] = {
5985 MockRead("HTTP/1."),
5986 MockRead(false, OK),
5987 };
5988
[email protected]31a2bfe2010-02-09 08:03:395989 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595990 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575991
[email protected]f1f3f0f82011-10-01 20:38:105992 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575993
5994 scoped_ptr<HttpTransaction> trans(
5995 new HttpNetworkTransaction(CreateSession(&session_deps)));
5996
[email protected]5a1d7ca2010-04-28 20:12:275997 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575998 EXPECT_EQ(ERR_IO_PENDING, rv);
5999
6000 rv = callback.WaitForResult();
6001 EXPECT_EQ(OK, rv);
6002
6003 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506004 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:576005
6006 EXPECT_TRUE(response->headers != NULL);
6007 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6008
6009 std::string response_data;
6010 rv = ReadTransaction(trans.get(), &response_data);
6011 EXPECT_EQ(OK, rv);
6012 EXPECT_EQ("", response_data);
6013}
6014
6015// Make sure that a dropped connection while draining the body for auth
6016// restart does the right thing.
6017TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
6018 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:276019 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:576020
6021 HttpRequestInfo request;
6022 request.method = "GET";
6023 request.url = GURL("http://www.google.com/");
6024 request.load_flags = 0;
6025
6026 MockWrite data_writes1[] = {
6027 MockWrite("GET / HTTP/1.1\r\n"
6028 "Host: www.google.com\r\n"
6029 "Connection: keep-alive\r\n\r\n"),
6030 };
6031
6032 MockRead data_reads1[] = {
6033 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6034 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6035 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6036 MockRead("Content-Length: 14\r\n\r\n"),
6037 MockRead("Unauth"),
6038 MockRead(true, ERR_CONNECTION_RESET),
6039 };
6040
[email protected]31a2bfe2010-02-09 08:03:396041 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6042 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:596043 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:576044
6045 // After calling trans->RestartWithAuth(), this is the request we should
6046 // be issuing -- the final header line contains the credentials.
6047 MockWrite data_writes2[] = {
6048 MockWrite("GET / HTTP/1.1\r\n"
6049 "Host: www.google.com\r\n"
6050 "Connection: keep-alive\r\n"
6051 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6052 };
6053
6054 // Lastly, the server responds with the actual content.
6055 MockRead data_reads2[] = {
6056 MockRead("HTTP/1.1 200 OK\r\n"),
6057 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6058 MockRead("Content-Length: 100\r\n\r\n"),
6059 MockRead(false, OK),
6060 };
6061
[email protected]31a2bfe2010-02-09 08:03:396062 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6063 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:596064 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:576065
[email protected]f1f3f0f82011-10-01 20:38:106066 TestOldCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:576067
[email protected]0b0bf032010-09-21 18:08:506068 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6069
[email protected]5a1d7ca2010-04-28 20:12:276070 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576071 EXPECT_EQ(ERR_IO_PENDING, rv);
6072
6073 rv = callback1.WaitForResult();
6074 EXPECT_EQ(OK, rv);
6075
6076 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506077 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046078 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:576079
[email protected]f1f3f0f82011-10-01 20:38:106080 TestOldCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:576081
[email protected]f3cf9802011-10-28 18:44:586082 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]0877e3d2009-10-17 22:29:576083 EXPECT_EQ(ERR_IO_PENDING, rv);
6084
6085 rv = callback2.WaitForResult();
6086 EXPECT_EQ(OK, rv);
6087
6088 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506089 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:576090 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6091 EXPECT_EQ(100, response->headers->GetContentLength());
6092}
6093
6094// Test HTTPS connections going through a proxy that sends extra data.
6095TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006096 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576097
6098 HttpRequestInfo request;
6099 request.method = "GET";
6100 request.url = GURL("https://www.google.com/");
6101 request.load_flags = 0;
6102
6103 MockRead proxy_reads[] = {
6104 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6105 MockRead(false, OK)
6106 };
6107
[email protected]31a2bfe2010-02-09 08:03:396108 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596109 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576110
[email protected]5ecc992a42009-11-11 01:41:596111 session_deps.socket_factory.AddSocketDataProvider(&data);
6112 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576113
[email protected]f1f3f0f82011-10-01 20:38:106114 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:576115
6116 session_deps.socket_factory.ResetNextMockIndexes();
6117
6118 scoped_ptr<HttpTransaction> trans(
6119 new HttpNetworkTransaction(CreateSession(&session_deps)));
6120
[email protected]5a1d7ca2010-04-28 20:12:276121 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576122 EXPECT_EQ(ERR_IO_PENDING, rv);
6123
6124 rv = callback.WaitForResult();
6125 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6126}
6127
[email protected]e22e1362009-11-23 21:31:126128TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466129 HttpRequestInfo request;
6130 request.method = "GET";
6131 request.url = GURL("http://www.google.com/");
6132 request.load_flags = 0;
6133
[email protected]cb9bf6ca2011-01-28 13:15:276134 SessionDependencies session_deps;
6135 scoped_ptr<HttpTransaction> trans(
6136 new HttpNetworkTransaction(CreateSession(&session_deps)));
6137
[email protected]e22e1362009-11-23 21:31:126138 MockRead data_reads[] = {
6139 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6140 MockRead(false, OK),
6141 };
[email protected]9492e4a2010-02-24 00:58:466142
6143 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6144 session_deps.socket_factory.AddSocketDataProvider(&data);
6145
[email protected]f1f3f0f82011-10-01 20:38:106146 TestOldCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:466147
[email protected]5a1d7ca2010-04-28 20:12:276148 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466149 EXPECT_EQ(ERR_IO_PENDING, rv);
6150
6151 EXPECT_EQ(OK, callback.WaitForResult());
6152
6153 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506154 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:466155
6156 EXPECT_TRUE(response->headers != NULL);
6157 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6158
6159 std::string response_data;
6160 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f0e2bf42011-07-22 21:21:446161 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126162}
6163
[email protected]95d88ffe2010-02-04 21:25:336164TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336165 HttpRequestInfo request;
6166 request.method = "POST";
6167 request.url = GURL("http://www.google.com/upload");
6168 request.upload_data = new UploadData;
6169 request.load_flags = 0;
6170
[email protected]cb9bf6ca2011-01-28 13:15:276171 SessionDependencies session_deps;
6172 scoped_ptr<HttpTransaction> trans(
6173 new HttpNetworkTransaction(CreateSession(&session_deps)));
6174
[email protected]95d88ffe2010-02-04 21:25:336175 FilePath temp_file_path;
6176 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6177 const uint64 kFakeSize = 100000; // file is actually blank
6178
6179 std::vector<UploadData::Element> elements;
6180 UploadData::Element element;
6181 element.SetToFilePath(temp_file_path);
6182 element.SetContentLength(kFakeSize);
6183 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536184 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336185 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6186
6187 MockRead data_reads[] = {
6188 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6189 MockRead("hello world"),
6190 MockRead(false, OK),
6191 };
[email protected]31a2bfe2010-02-09 08:03:396192 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336193 session_deps.socket_factory.AddSocketDataProvider(&data);
6194
[email protected]f1f3f0f82011-10-01 20:38:106195 TestOldCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:336196
[email protected]5a1d7ca2010-04-28 20:12:276197 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336198 EXPECT_EQ(ERR_IO_PENDING, rv);
6199
6200 rv = callback.WaitForResult();
6201 EXPECT_EQ(OK, rv);
6202
6203 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506204 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:336205
6206 EXPECT_TRUE(response->headers != NULL);
6207 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6208
6209 std::string response_data;
6210 rv = ReadTransaction(trans.get(), &response_data);
6211 EXPECT_EQ(OK, rv);
6212 EXPECT_EQ("hello world", response_data);
6213
6214 file_util::Delete(temp_file_path, false);
6215}
6216
[email protected]6624b4622010-03-29 19:58:366217TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276218 HttpRequestInfo request;
6219 request.method = "POST";
6220 request.url = GURL("http://www.google.com/upload");
6221 request.upload_data = new UploadData;
6222 request.load_flags = 0;
6223
[email protected]6624b4622010-03-29 19:58:366224 // If we try to upload an unreadable file, the network stack should report
6225 // the file size as zero and upload zero bytes for that file.
6226 SessionDependencies session_deps;
6227 scoped_ptr<HttpTransaction> trans(
6228 new HttpNetworkTransaction(CreateSession(&session_deps)));
6229
6230 FilePath temp_file;
6231 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6232 std::string temp_file_content("Unreadable file.");
6233 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6234 temp_file_content.length()));
6235 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6236
[email protected]6624b4622010-03-29 19:58:366237 std::vector<UploadData::Element> elements;
6238 UploadData::Element element;
6239 element.SetToFilePath(temp_file);
6240 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536241 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366242
6243 MockRead data_reads[] = {
6244 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6245 MockRead(false, OK),
6246 };
6247 MockWrite data_writes[] = {
6248 MockWrite("POST /upload HTTP/1.1\r\n"
6249 "Host: www.google.com\r\n"
6250 "Connection: keep-alive\r\n"
6251 "Content-Length: 0\r\n\r\n"),
6252 MockWrite(false, OK),
6253 };
6254 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6255 arraysize(data_writes));
6256 session_deps.socket_factory.AddSocketDataProvider(&data);
6257
[email protected]f1f3f0f82011-10-01 20:38:106258 TestOldCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:366259
[email protected]5a1d7ca2010-04-28 20:12:276260 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366261 EXPECT_EQ(ERR_IO_PENDING, rv);
6262
6263 rv = callback.WaitForResult();
6264 EXPECT_EQ(OK, rv);
6265
6266 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506267 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366268 EXPECT_TRUE(response->headers != NULL);
6269 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6270
6271 file_util::Delete(temp_file, false);
6272}
6273
6274TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276275 HttpRequestInfo request;
6276 request.method = "POST";
6277 request.url = GURL("http://www.google.com/upload");
6278 request.upload_data = new UploadData;
6279 request.load_flags = 0;
6280
[email protected]6624b4622010-03-29 19:58:366281 SessionDependencies session_deps;
6282 scoped_ptr<HttpTransaction> trans(
6283 new HttpNetworkTransaction(CreateSession(&session_deps)));
6284
6285 FilePath temp_file;
6286 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6287 std::string temp_file_contents("Unreadable file.");
6288 std::string unreadable_contents(temp_file_contents.length(), '\0');
6289 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6290 temp_file_contents.length()));
6291
[email protected]6624b4622010-03-29 19:58:366292 std::vector<UploadData::Element> elements;
6293 UploadData::Element element;
6294 element.SetToFilePath(temp_file);
6295 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536296 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366297
6298 MockRead data_reads[] = {
6299 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6300 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6301 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6302
6303 MockRead("HTTP/1.1 200 OK\r\n"),
6304 MockRead("Content-Length: 0\r\n\r\n"),
6305 MockRead(false, OK),
6306 };
6307 MockWrite data_writes[] = {
6308 MockWrite("POST /upload HTTP/1.1\r\n"
6309 "Host: www.google.com\r\n"
6310 "Connection: keep-alive\r\n"
6311 "Content-Length: 16\r\n\r\n"),
6312 MockWrite(false, temp_file_contents.c_str()),
6313
6314 MockWrite("POST /upload HTTP/1.1\r\n"
6315 "Host: www.google.com\r\n"
6316 "Connection: keep-alive\r\n"
6317 "Content-Length: 16\r\n"
6318 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6319 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6320 MockWrite(false, OK),
6321 };
6322 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6323 arraysize(data_writes));
6324 session_deps.socket_factory.AddSocketDataProvider(&data);
6325
[email protected]f1f3f0f82011-10-01 20:38:106326 TestOldCompletionCallback callback1;
[email protected]6624b4622010-03-29 19:58:366327
[email protected]5a1d7ca2010-04-28 20:12:276328 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366329 EXPECT_EQ(ERR_IO_PENDING, rv);
6330
6331 rv = callback1.WaitForResult();
6332 EXPECT_EQ(OK, rv);
6333
6334 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:046335 ASSERT_TRUE(response != NULL);
6336 ASSERT_TRUE(response->headers != NULL);
[email protected]6624b4622010-03-29 19:58:366337 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
[email protected]79cb5c12011-09-12 13:12:046338 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]6624b4622010-03-29 19:58:366339
6340 // Now make the file unreadable and try again.
6341 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6342
[email protected]f1f3f0f82011-10-01 20:38:106343 TestOldCompletionCallback callback2;
[email protected]6624b4622010-03-29 19:58:366344
[email protected]f3cf9802011-10-28 18:44:586345 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback2);
[email protected]6624b4622010-03-29 19:58:366346 EXPECT_EQ(ERR_IO_PENDING, rv);
6347
6348 rv = callback2.WaitForResult();
6349 EXPECT_EQ(OK, rv);
6350
6351 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506352 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366353 EXPECT_TRUE(response->headers != NULL);
6354 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6355 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6356
6357 file_util::Delete(temp_file, false);
6358}
6359
[email protected]aeefc9e82010-02-19 16:18:276360// Tests that changes to Auth realms are treated like auth rejections.
6361TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6362 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276363
6364 HttpRequestInfo request;
6365 request.method = "GET";
6366 request.url = GURL("http://www.google.com/");
6367 request.load_flags = 0;
6368
6369 // First transaction will request a resource and receive a Basic challenge
6370 // with realm="first_realm".
6371 MockWrite data_writes1[] = {
6372 MockWrite("GET / HTTP/1.1\r\n"
6373 "Host: www.google.com\r\n"
6374 "Connection: keep-alive\r\n"
6375 "\r\n"),
6376 };
6377 MockRead data_reads1[] = {
6378 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6379 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6380 "\r\n"),
6381 };
6382
6383 // After calling trans->RestartWithAuth(), provide an Authentication header
6384 // for first_realm. The server will reject and provide a challenge with
6385 // second_realm.
6386 MockWrite data_writes2[] = {
6387 MockWrite("GET / HTTP/1.1\r\n"
6388 "Host: www.google.com\r\n"
6389 "Connection: keep-alive\r\n"
6390 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6391 "\r\n"),
6392 };
6393 MockRead data_reads2[] = {
6394 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6395 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6396 "\r\n"),
6397 };
6398
6399 // This again fails, and goes back to first_realm. Make sure that the
6400 // entry is removed from cache.
6401 MockWrite data_writes3[] = {
6402 MockWrite("GET / HTTP/1.1\r\n"
6403 "Host: www.google.com\r\n"
6404 "Connection: keep-alive\r\n"
6405 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6406 "\r\n"),
6407 };
6408 MockRead data_reads3[] = {
6409 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6410 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6411 "\r\n"),
6412 };
6413
6414 // Try one last time (with the correct password) and get the resource.
6415 MockWrite data_writes4[] = {
6416 MockWrite("GET / HTTP/1.1\r\n"
6417 "Host: www.google.com\r\n"
6418 "Connection: keep-alive\r\n"
6419 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6420 "\r\n"),
6421 };
6422 MockRead data_reads4[] = {
6423 MockRead("HTTP/1.1 200 OK\r\n"
6424 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506425 "Content-Length: 5\r\n"
6426 "\r\n"
6427 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276428 };
6429
6430 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6431 data_writes1, arraysize(data_writes1));
6432 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6433 data_writes2, arraysize(data_writes2));
6434 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6435 data_writes3, arraysize(data_writes3));
6436 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6437 data_writes4, arraysize(data_writes4));
6438 session_deps.socket_factory.AddSocketDataProvider(&data1);
6439 session_deps.socket_factory.AddSocketDataProvider(&data2);
6440 session_deps.socket_factory.AddSocketDataProvider(&data3);
6441 session_deps.socket_factory.AddSocketDataProvider(&data4);
6442
[email protected]f1f3f0f82011-10-01 20:38:106443 TestOldCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:276444
[email protected]0b0bf032010-09-21 18:08:506445 scoped_ptr<HttpTransaction> trans(
6446 new HttpNetworkTransaction(CreateSession(&session_deps)));
6447
[email protected]aeefc9e82010-02-19 16:18:276448 // Issue the first request with Authorize headers. There should be a
6449 // password prompt for first_realm waiting to be filled in after the
6450 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276451 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276452 EXPECT_EQ(ERR_IO_PENDING, rv);
6453 rv = callback1.WaitForResult();
6454 EXPECT_EQ(OK, rv);
6455 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506456 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046457 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6458 ASSERT_FALSE(challenge == NULL);
6459 EXPECT_FALSE(challenge->is_proxy);
6460 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6461 EXPECT_EQ("first_realm", challenge->realm);
6462 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276463
6464 // Issue the second request with an incorrect password. There should be a
6465 // password prompt for second_realm waiting to be filled in after the
6466 // transaction completes.
[email protected]f1f3f0f82011-10-01 20:38:106467 TestOldCompletionCallback callback2;
[email protected]f3cf9802011-10-28 18:44:586468 rv = trans->RestartWithAuth(AuthCredentials(kFirst, kBaz), &callback2);
[email protected]aeefc9e82010-02-19 16:18:276469 EXPECT_EQ(ERR_IO_PENDING, rv);
6470 rv = callback2.WaitForResult();
6471 EXPECT_EQ(OK, rv);
6472 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506473 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046474 challenge = response->auth_challenge.get();
6475 ASSERT_FALSE(challenge == NULL);
6476 EXPECT_FALSE(challenge->is_proxy);
6477 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6478 EXPECT_EQ("second_realm", challenge->realm);
6479 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276480
6481 // Issue the third request with another incorrect password. There should be
6482 // a password prompt for first_realm waiting to be filled in. If the password
6483 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6484 // first_realm was not correctly removed.
[email protected]f1f3f0f82011-10-01 20:38:106485 TestOldCompletionCallback callback3;
[email protected]f3cf9802011-10-28 18:44:586486 rv = trans->RestartWithAuth(AuthCredentials(kSecond, kFou), &callback3);
[email protected]aeefc9e82010-02-19 16:18:276487 EXPECT_EQ(ERR_IO_PENDING, rv);
6488 rv = callback3.WaitForResult();
6489 EXPECT_EQ(OK, rv);
6490 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506491 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046492 challenge = response->auth_challenge.get();
6493 ASSERT_FALSE(challenge == NULL);
6494 EXPECT_FALSE(challenge->is_proxy);
6495 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6496 EXPECT_EQ("first_realm", challenge->realm);
6497 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276498
6499 // Issue the fourth request with the correct password and username.
[email protected]f1f3f0f82011-10-01 20:38:106500 TestOldCompletionCallback callback4;
[email protected]f3cf9802011-10-28 18:44:586501 rv = trans->RestartWithAuth(AuthCredentials(kFirst, kBar), &callback4);
[email protected]aeefc9e82010-02-19 16:18:276502 EXPECT_EQ(ERR_IO_PENDING, rv);
6503 rv = callback4.WaitForResult();
6504 EXPECT_EQ(OK, rv);
6505 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506506 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:276507 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6508}
6509
[email protected]564b4912010-03-09 16:30:426510TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]5285d972011-10-18 18:56:346511 HttpStreamFactory::set_next_protos(MakeNextProtos("foo", "bar", NULL));
[email protected]8e6441ca2010-08-19 05:56:386512 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426513
[email protected]564b4912010-03-09 16:30:426514 SessionDependencies session_deps;
6515
6516 MockRead data_reads[] = {
6517 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356518 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426519 MockRead("hello world"),
6520 MockRead(false, OK),
6521 };
6522
6523 HttpRequestInfo request;
6524 request.method = "GET";
6525 request.url = GURL("http://www.google.com/");
6526 request.load_flags = 0;
6527
6528 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6529
6530 session_deps.socket_factory.AddSocketDataProvider(&data);
6531
[email protected]f1f3f0f82011-10-01 20:38:106532 TestOldCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426533
6534 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6535 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6536
[email protected]5a1d7ca2010-04-28 20:12:276537 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426538 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536539
[email protected]2fbaecf22010-07-22 22:20:356540 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]17291a022011-10-10 07:32:536541 const HttpServerProperties& http_server_properties =
6542 *session->http_server_properties();
[email protected]564b4912010-03-09 16:30:426543 EXPECT_FALSE(
[email protected]17291a022011-10-10 07:32:536544 http_server_properties.HasAlternateProtocol(http_host_port_pair));
[email protected]564b4912010-03-09 16:30:426545
6546 EXPECT_EQ(OK, callback.WaitForResult());
6547
6548 const HttpResponseInfo* response = trans->GetResponseInfo();
6549 ASSERT_TRUE(response != NULL);
6550 ASSERT_TRUE(response->headers != NULL);
6551 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536552 EXPECT_FALSE(response->was_fetched_via_spdy);
6553 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426554
6555 std::string response_data;
6556 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6557 EXPECT_EQ("hello world", response_data);
6558
[email protected]17291a022011-10-10 07:32:536559 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6560 const PortAlternateProtocolPair alternate =
6561 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6562 PortAlternateProtocolPair expected_alternate;
[email protected]564b4912010-03-09 16:30:426563 expected_alternate.port = 443;
[email protected]17291a022011-10-10 07:32:536564 expected_alternate.protocol = NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426565 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426566
[email protected]8e6441ca2010-08-19 05:56:386567 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]5285d972011-10-18 18:56:346568 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]564b4912010-03-09 16:30:426569}
6570
[email protected]8b95ed62011-03-18 18:12:036571TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386572 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426573 SessionDependencies session_deps;
6574
6575 HttpRequestInfo request;
6576 request.method = "GET";
6577 request.url = GURL("http://www.google.com/");
6578 request.load_flags = 0;
6579
6580 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6581 StaticSocketDataProvider first_data;
6582 first_data.set_connect_data(mock_connect);
6583 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6584
6585 MockRead data_reads[] = {
6586 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6587 MockRead("hello world"),
6588 MockRead(true, OK),
6589 };
6590 StaticSocketDataProvider second_data(
6591 data_reads, arraysize(data_reads), NULL, 0);
6592 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6593
[email protected]564b4912010-03-09 16:30:426594 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6595
[email protected]17291a022011-10-10 07:32:536596 HttpServerProperties* http_server_properties =
6597 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116598 // Port must be < 1024, or the header will be ignored (since initial port was
6599 // port 80 (another restricted port).
[email protected]17291a022011-10-10 07:32:536600 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116601 HostPortPair::FromURL(request.url),
6602 666 /* port is ignored by MockConnect anyway */,
[email protected]17291a022011-10-10 07:32:536603 NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426604
6605 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]3912662a32011-10-04 00:51:116606 TestOldCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426607
[email protected]5a1d7ca2010-04-28 20:12:276608 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426609 EXPECT_EQ(ERR_IO_PENDING, rv);
6610 EXPECT_EQ(OK, callback.WaitForResult());
6611
6612 const HttpResponseInfo* response = trans->GetResponseInfo();
6613 ASSERT_TRUE(response != NULL);
6614 ASSERT_TRUE(response->headers != NULL);
6615 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6616
6617 std::string response_data;
6618 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6619 EXPECT_EQ("hello world", response_data);
6620
[email protected]17291a022011-10-10 07:32:536621 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116622 HostPortPair::FromURL(request.url)));
[email protected]17291a022011-10-10 07:32:536623 const PortAlternateProtocolPair alternate =
6624 http_server_properties->GetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116625 HostPortPair::FromURL(request.url));
[email protected]17291a022011-10-10 07:32:536626 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386627 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426628}
6629
[email protected]3912662a32011-10-04 00:51:116630TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6631 // Ensure that we're not allowed to redirect traffic via an alternate
6632 // protocol to an unrestricted (port >= 1024) when the original traffic was
6633 // on a restricted port (port < 1024). Ensure that we can redirect in all
6634 // other cases.
6635 HttpStreamFactory::set_use_alternate_protocols(true);
6636 SessionDependencies session_deps;
6637
6638 HttpRequestInfo restricted_port_request;
6639 restricted_port_request.method = "GET";
6640 restricted_port_request.url = GURL("http://www.google.com:1023/");
6641 restricted_port_request.load_flags = 0;
6642
6643 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6644 StaticSocketDataProvider first_data;
6645 first_data.set_connect_data(mock_connect);
6646 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6647
6648 MockRead data_reads[] = {
6649 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6650 MockRead("hello world"),
6651 MockRead(true, OK),
6652 };
6653 StaticSocketDataProvider second_data(
6654 data_reads, arraysize(data_reads), NULL, 0);
6655 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6656
6657 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6658
[email protected]17291a022011-10-10 07:32:536659 HttpServerProperties* http_server_properties =
6660 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116661 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536662 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116663 HostPortPair::FromURL(restricted_port_request.url),
6664 kUnrestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536665 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116666
6667 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6668 TestOldCompletionCallback callback;
6669
6670 int rv = trans->Start(&restricted_port_request, &callback, BoundNetLog());
6671 EXPECT_EQ(ERR_IO_PENDING, rv);
6672 // Invalid change to unrestricted port should fail.
6673 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6674
6675 HttpStreamFactory::set_use_alternate_protocols(false);
6676}
6677
6678TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6679 // Ensure that we're not allowed to redirect traffic via an alternate
6680 // protocol to an unrestricted (port >= 1024) when the original traffic was
6681 // on a restricted port (port < 1024). Ensure that we can redirect in all
6682 // other cases.
6683 HttpStreamFactory::set_use_alternate_protocols(true);
6684 SessionDependencies session_deps;
6685
6686 HttpRequestInfo restricted_port_request;
6687 restricted_port_request.method = "GET";
6688 restricted_port_request.url = GURL("http://www.google.com:1023/");
6689 restricted_port_request.load_flags = 0;
6690
6691 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6692 StaticSocketDataProvider first_data;
6693 first_data.set_connect_data(mock_connect);
6694 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6695
6696 MockRead data_reads[] = {
6697 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6698 MockRead("hello world"),
6699 MockRead(true, OK),
6700 };
6701 StaticSocketDataProvider second_data(
6702 data_reads, arraysize(data_reads), NULL, 0);
6703 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6704
6705 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6706
[email protected]17291a022011-10-10 07:32:536707 HttpServerProperties* http_server_properties =
6708 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116709 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536710 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116711 HostPortPair::FromURL(restricted_port_request.url),
6712 kRestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536713 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116714
6715 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6716 TestOldCompletionCallback callback;
6717
6718 int rv = trans->Start(&restricted_port_request, &callback, BoundNetLog());
6719 EXPECT_EQ(ERR_IO_PENDING, rv);
6720 // Valid change to restricted port should pass.
6721 EXPECT_EQ(OK, callback.WaitForResult());
6722
6723 HttpStreamFactory::set_use_alternate_protocols(false);
6724}
6725
6726TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6727 // Ensure that we're not allowed to redirect traffic via an alternate
6728 // protocol to an unrestricted (port >= 1024) when the original traffic was
6729 // on a restricted port (port < 1024). Ensure that we can redirect in all
6730 // other cases.
6731 HttpStreamFactory::set_use_alternate_protocols(true);
6732 SessionDependencies session_deps;
6733
6734 HttpRequestInfo unrestricted_port_request;
6735 unrestricted_port_request.method = "GET";
6736 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6737 unrestricted_port_request.load_flags = 0;
6738
6739 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6740 StaticSocketDataProvider first_data;
6741 first_data.set_connect_data(mock_connect);
6742 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6743
6744 MockRead data_reads[] = {
6745 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6746 MockRead("hello world"),
6747 MockRead(true, OK),
6748 };
6749 StaticSocketDataProvider second_data(
6750 data_reads, arraysize(data_reads), NULL, 0);
6751 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6752
6753 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6754
[email protected]17291a022011-10-10 07:32:536755 HttpServerProperties* http_server_properties =
6756 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116757 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536758 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116759 HostPortPair::FromURL(unrestricted_port_request.url),
6760 kRestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536761 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116762
6763 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6764 TestOldCompletionCallback callback;
6765
6766 int rv = trans->Start(&unrestricted_port_request, &callback, BoundNetLog());
6767 EXPECT_EQ(ERR_IO_PENDING, rv);
6768 // Valid change to restricted port should pass.
6769 EXPECT_EQ(OK, callback.WaitForResult());
6770
6771 HttpStreamFactory::set_use_alternate_protocols(false);
6772}
6773
6774TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6775 // Ensure that we're not allowed to redirect traffic via an alternate
6776 // protocol to an unrestricted (port >= 1024) when the original traffic was
6777 // on a restricted port (port < 1024). Ensure that we can redirect in all
6778 // other cases.
6779 HttpStreamFactory::set_use_alternate_protocols(true);
6780 SessionDependencies session_deps;
6781
6782 HttpRequestInfo unrestricted_port_request;
6783 unrestricted_port_request.method = "GET";
6784 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6785 unrestricted_port_request.load_flags = 0;
6786
6787 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6788 StaticSocketDataProvider first_data;
6789 first_data.set_connect_data(mock_connect);
6790 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6791
6792 MockRead data_reads[] = {
6793 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6794 MockRead("hello world"),
6795 MockRead(true, OK),
6796 };
6797 StaticSocketDataProvider second_data(
6798 data_reads, arraysize(data_reads), NULL, 0);
6799 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6800
6801 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6802
[email protected]17291a022011-10-10 07:32:536803 HttpServerProperties* http_server_properties =
6804 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116805 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536806 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116807 HostPortPair::FromURL(unrestricted_port_request.url),
6808 kUnrestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536809 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116810
6811 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6812 TestOldCompletionCallback callback;
6813
6814 int rv = trans->Start(&unrestricted_port_request, &callback, BoundNetLog());
6815 EXPECT_EQ(ERR_IO_PENDING, rv);
6816 // Valid change to an unrestricted port should pass.
6817 EXPECT_EQ(OK, callback.WaitForResult());
6818
6819 HttpStreamFactory::set_use_alternate_protocols(false);
6820}
6821
[email protected]2ff8b312010-04-26 22:20:546822TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386823 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346824 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:546825 SessionDependencies session_deps;
6826
6827 HttpRequestInfo request;
6828 request.method = "GET";
6829 request.url = GURL("http://www.google.com/");
6830 request.load_flags = 0;
6831
6832 MockRead data_reads[] = {
6833 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356834 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546835 MockRead("hello world"),
6836 MockRead(true, OK),
6837 };
6838
6839 StaticSocketDataProvider first_transaction(
6840 data_reads, arraysize(data_reads), NULL, 0);
6841 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6842
6843 SSLSocketDataProvider ssl(true, OK);
6844 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356845 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536846 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546847 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6848
[email protected]2bd93022010-07-17 00:58:446849 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136850 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546851
[email protected]2bd93022010-07-17 00:58:446852 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6853 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546854 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136855 CreateMockRead(*resp),
6856 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546857 MockRead(true, 0, 0),
6858 };
6859
6860 scoped_refptr<DelayedSocketData> spdy_data(
6861 new DelayedSocketData(
6862 1, // wait for one write to finish before reading.
6863 spdy_reads, arraysize(spdy_reads),
6864 spdy_writes, arraysize(spdy_writes)));
6865 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6866
[email protected]2d6728692011-03-12 01:39:556867 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6868 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6869 NULL, 0, NULL, 0);
6870 hanging_non_alternate_protocol_socket.set_connect_data(
6871 never_finishing_connect);
6872 session_deps.socket_factory.AddSocketDataProvider(
6873 &hanging_non_alternate_protocol_socket);
6874
[email protected]f1f3f0f82011-10-01 20:38:106875 TestOldCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:546876
6877 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6878 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6879
[email protected]5a1d7ca2010-04-28 20:12:276880 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546881 EXPECT_EQ(ERR_IO_PENDING, rv);
6882 EXPECT_EQ(OK, callback.WaitForResult());
6883
6884 const HttpResponseInfo* response = trans->GetResponseInfo();
6885 ASSERT_TRUE(response != NULL);
6886 ASSERT_TRUE(response->headers != NULL);
6887 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6888
6889 std::string response_data;
6890 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6891 EXPECT_EQ("hello world", response_data);
6892
6893 trans.reset(new HttpNetworkTransaction(session));
6894
[email protected]5a1d7ca2010-04-28 20:12:276895 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546896 EXPECT_EQ(ERR_IO_PENDING, rv);
6897 EXPECT_EQ(OK, callback.WaitForResult());
6898
6899 response = trans->GetResponseInfo();
6900 ASSERT_TRUE(response != NULL);
6901 ASSERT_TRUE(response->headers != NULL);
6902 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536903 EXPECT_TRUE(response->was_fetched_via_spdy);
6904 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546905
6906 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6907 EXPECT_EQ("hello!", response_data);
6908
[email protected]5285d972011-10-18 18:56:346909 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:386910 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546911}
6912
[email protected]2d6728692011-03-12 01:39:556913TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6914 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346915 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556916 SessionDependencies session_deps;
6917
6918 HttpRequestInfo request;
6919 request.method = "GET";
6920 request.url = GURL("http://www.google.com/");
6921 request.load_flags = 0;
6922
6923 MockRead data_reads[] = {
6924 MockRead("HTTP/1.1 200 OK\r\n"),
6925 MockRead(kAlternateProtocolHttpHeader),
6926 MockRead("hello world"),
6927 MockRead(true, OK),
6928 };
6929
6930 StaticSocketDataProvider first_transaction(
6931 data_reads, arraysize(data_reads), NULL, 0);
6932 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6933 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6934
6935 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6936 StaticSocketDataProvider hanging_socket(
6937 NULL, 0, NULL, 0);
6938 hanging_socket.set_connect_data(never_finishing_connect);
6939 // Socket 2 and 3 are the hanging Alternate-Protocol and
6940 // non-Alternate-Protocol jobs from the 2nd transaction.
6941 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6942 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6943
6944 SSLSocketDataProvider ssl(true, OK);
6945 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6946 ssl.next_proto = "spdy/2";
6947 ssl.was_npn_negotiated = true;
6948 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6949
6950 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6951 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6952 MockWrite spdy_writes[] = {
6953 CreateMockWrite(*req1),
6954 CreateMockWrite(*req2),
6955 };
6956 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6957 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6958 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6959 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6960 MockRead spdy_reads[] = {
6961 CreateMockRead(*resp1),
6962 CreateMockRead(*data1),
6963 CreateMockRead(*resp2),
6964 CreateMockRead(*data2),
6965 MockRead(true, 0, 0),
6966 };
6967
6968 scoped_refptr<DelayedSocketData> spdy_data(
6969 new DelayedSocketData(
6970 2, // wait for writes to finish before reading.
6971 spdy_reads, arraysize(spdy_reads),
6972 spdy_writes, arraysize(spdy_writes)));
6973 // Socket 4 is the successful Alternate-Protocol for transaction 3.
6974 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6975
6976 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6977 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6978
6979 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f1f3f0f82011-10-01 20:38:106980 TestOldCompletionCallback callback1;
[email protected]2d6728692011-03-12 01:39:556981 HttpNetworkTransaction trans1(session);
6982
6983 int rv = trans1.Start(&request, &callback1, BoundNetLog());
6984 EXPECT_EQ(ERR_IO_PENDING, rv);
6985 EXPECT_EQ(OK, callback1.WaitForResult());
6986
6987 const HttpResponseInfo* response = trans1.GetResponseInfo();
6988 ASSERT_TRUE(response != NULL);
6989 ASSERT_TRUE(response->headers != NULL);
6990 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6991
6992 std::string response_data;
6993 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6994 EXPECT_EQ("hello world", response_data);
6995
[email protected]f1f3f0f82011-10-01 20:38:106996 TestOldCompletionCallback callback2;
[email protected]2d6728692011-03-12 01:39:556997 HttpNetworkTransaction trans2(session);
6998 rv = trans2.Start(&request, &callback2, BoundNetLog());
6999 EXPECT_EQ(ERR_IO_PENDING, rv);
7000
[email protected]f1f3f0f82011-10-01 20:38:107001 TestOldCompletionCallback callback3;
[email protected]2d6728692011-03-12 01:39:557002 HttpNetworkTransaction trans3(session);
7003 rv = trans3.Start(&request, &callback3, BoundNetLog());
7004 EXPECT_EQ(ERR_IO_PENDING, rv);
7005
7006 EXPECT_EQ(OK, callback2.WaitForResult());
7007 EXPECT_EQ(OK, callback3.WaitForResult());
7008
7009 response = trans2.GetResponseInfo();
7010 ASSERT_TRUE(response != NULL);
7011 ASSERT_TRUE(response->headers != NULL);
7012 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7013 EXPECT_TRUE(response->was_fetched_via_spdy);
7014 EXPECT_TRUE(response->was_npn_negotiated);
7015 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
7016 EXPECT_EQ("hello!", response_data);
7017
7018 response = trans3.GetResponseInfo();
7019 ASSERT_TRUE(response != NULL);
7020 ASSERT_TRUE(response->headers != NULL);
7021 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7022 EXPECT_TRUE(response->was_fetched_via_spdy);
7023 EXPECT_TRUE(response->was_npn_negotiated);
7024 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
7025 EXPECT_EQ("hello!", response_data);
7026
[email protected]5285d972011-10-18 18:56:347027 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557028 HttpStreamFactory::set_use_alternate_protocols(false);
7029}
7030
7031TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
7032 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347033 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:557034 SessionDependencies session_deps;
7035
7036 HttpRequestInfo request;
7037 request.method = "GET";
7038 request.url = GURL("http://www.google.com/");
7039 request.load_flags = 0;
7040
7041 MockRead data_reads[] = {
7042 MockRead("HTTP/1.1 200 OK\r\n"),
7043 MockRead(kAlternateProtocolHttpHeader),
7044 MockRead("hello world"),
7045 MockRead(true, OK),
7046 };
7047
7048 StaticSocketDataProvider first_transaction(
7049 data_reads, arraysize(data_reads), NULL, 0);
7050 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7051
7052 SSLSocketDataProvider ssl(true, OK);
7053 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7054 ssl.next_proto = "spdy/2";
7055 ssl.was_npn_negotiated = true;
7056 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7057
7058 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7059 StaticSocketDataProvider hanging_alternate_protocol_socket(
7060 NULL, 0, NULL, 0);
7061 hanging_alternate_protocol_socket.set_connect_data(
7062 never_finishing_connect);
7063 session_deps.socket_factory.AddSocketDataProvider(
7064 &hanging_alternate_protocol_socket);
7065
7066 // 2nd request is just a copy of the first one, over HTTP again.
7067 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7068
[email protected]f1f3f0f82011-10-01 20:38:107069 TestOldCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:557070
7071 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7072 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7073
7074 int rv = trans->Start(&request, &callback, BoundNetLog());
7075 EXPECT_EQ(ERR_IO_PENDING, rv);
7076 EXPECT_EQ(OK, callback.WaitForResult());
7077
7078 const HttpResponseInfo* response = trans->GetResponseInfo();
7079 ASSERT_TRUE(response != NULL);
7080 ASSERT_TRUE(response->headers != NULL);
7081 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7082
7083 std::string response_data;
7084 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7085 EXPECT_EQ("hello world", response_data);
7086
7087 trans.reset(new HttpNetworkTransaction(session));
7088
7089 rv = trans->Start(&request, &callback, BoundNetLog());
7090 EXPECT_EQ(ERR_IO_PENDING, rv);
7091 EXPECT_EQ(OK, callback.WaitForResult());
7092
7093 response = trans->GetResponseInfo();
7094 ASSERT_TRUE(response != NULL);
7095 ASSERT_TRUE(response->headers != NULL);
7096 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7097 EXPECT_FALSE(response->was_fetched_via_spdy);
7098 EXPECT_FALSE(response->was_npn_negotiated);
7099
7100 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7101 EXPECT_EQ("hello world", response_data);
7102
[email protected]5285d972011-10-18 18:56:347103 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557104 HttpStreamFactory::set_use_alternate_protocols(false);
7105}
7106
[email protected]631f1322010-04-30 17:59:117107class CapturingProxyResolver : public ProxyResolver {
7108 public:
7109 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7110 virtual ~CapturingProxyResolver() {}
7111
7112 virtual int GetProxyForURL(const GURL& url,
7113 ProxyInfo* results,
[email protected]f1f3f0f82011-10-01 20:38:107114 OldCompletionCallback* callback,
[email protected]631f1322010-04-30 17:59:117115 RequestHandle* request,
7116 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:407117 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7118 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:427119 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:117120 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:427121 return OK;
[email protected]631f1322010-04-30 17:59:117122 }
7123
7124 virtual void CancelRequest(RequestHandle request) {
7125 NOTREACHED();
7126 }
7127
[email protected]f2c971f2011-11-08 00:33:177128 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
7129 NOTREACHED();
7130 return LOAD_STATE_IDLE;
7131 }
7132
7133 virtual LoadState GetLoadStateThreadSafe(
7134 RequestHandle request) const OVERRIDE {
7135 NOTREACHED();
7136 return LOAD_STATE_IDLE;
7137 }
7138
[email protected]1e605472010-12-16 21:41:407139 virtual void CancelSetPacScript() {
7140 NOTREACHED();
7141 }
7142
[email protected]24476402010-07-20 20:55:177143 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]f1f3f0f82011-10-01 20:38:107144 OldCompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:427145 return OK;
[email protected]631f1322010-04-30 17:59:117146 }
7147
[email protected]24476402010-07-20 20:55:177148 const std::vector<GURL>& resolved() const { return resolved_; }
7149
7150 private:
[email protected]631f1322010-04-30 17:59:117151 std::vector<GURL> resolved_;
7152
7153 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7154};
7155
[email protected]631f1322010-04-30 17:59:117156TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:387157 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347158 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]631f1322010-04-30 17:59:117159
7160 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:427161 proxy_config.set_auto_detect(true);
7162 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:117163
[email protected]631f1322010-04-30 17:59:117164 CapturingProxyResolver* capturing_proxy_resolver =
7165 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:387166 SessionDependencies session_deps(new ProxyService(
7167 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7168 NULL));
[email protected]631f1322010-04-30 17:59:117169
7170 HttpRequestInfo request;
7171 request.method = "GET";
7172 request.url = GURL("http://www.google.com/");
7173 request.load_flags = 0;
7174
7175 MockRead data_reads[] = {
7176 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357177 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:117178 MockRead("hello world"),
7179 MockRead(true, OK),
7180 };
7181
7182 StaticSocketDataProvider first_transaction(
7183 data_reads, arraysize(data_reads), NULL, 0);
7184 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7185
7186 SSLSocketDataProvider ssl(true, OK);
7187 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357188 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537189 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:117190 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7191
[email protected]2bd93022010-07-17 00:58:447192 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:117193 MockWrite spdy_writes[] = {
7194 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7195 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:427196 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:137197 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:117198 };
7199
[email protected]d911f1b2010-05-05 22:39:427200 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7201
[email protected]2bd93022010-07-17 00:58:447202 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7203 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:117204 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:427205 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:137206 CreateMockRead(*resp.get(), 4), // 2, 4
7207 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:427208 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:117209 };
7210
[email protected]d911f1b2010-05-05 22:39:427211 scoped_refptr<OrderedSocketData> spdy_data(
7212 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:117213 spdy_reads, arraysize(spdy_reads),
7214 spdy_writes, arraysize(spdy_writes)));
7215 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7216
[email protected]2d6728692011-03-12 01:39:557217 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7218 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7219 NULL, 0, NULL, 0);
7220 hanging_non_alternate_protocol_socket.set_connect_data(
7221 never_finishing_connect);
7222 session_deps.socket_factory.AddSocketDataProvider(
7223 &hanging_non_alternate_protocol_socket);
7224
[email protected]f1f3f0f82011-10-01 20:38:107225 TestOldCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:117226
7227 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7228 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7229
7230 int rv = trans->Start(&request, &callback, BoundNetLog());
7231 EXPECT_EQ(ERR_IO_PENDING, rv);
7232 EXPECT_EQ(OK, callback.WaitForResult());
7233
7234 const HttpResponseInfo* response = trans->GetResponseInfo();
7235 ASSERT_TRUE(response != NULL);
7236 ASSERT_TRUE(response->headers != NULL);
7237 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537238 EXPECT_FALSE(response->was_fetched_via_spdy);
7239 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117240
7241 std::string response_data;
7242 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7243 EXPECT_EQ("hello world", response_data);
7244
7245 trans.reset(new HttpNetworkTransaction(session));
7246
7247 rv = trans->Start(&request, &callback, BoundNetLog());
7248 EXPECT_EQ(ERR_IO_PENDING, rv);
7249 EXPECT_EQ(OK, callback.WaitForResult());
7250
7251 response = trans->GetResponseInfo();
7252 ASSERT_TRUE(response != NULL);
7253 ASSERT_TRUE(response->headers != NULL);
7254 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537255 EXPECT_TRUE(response->was_fetched_via_spdy);
7256 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117257
7258 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7259 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557260 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427261 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117262 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427263 EXPECT_EQ("https://www.google.com/",
7264 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117265
[email protected]5285d972011-10-18 18:56:347266 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387267 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117268}
[email protected]631f1322010-04-30 17:59:117269
[email protected]2ff8b312010-04-26 22:20:547270TEST_F(HttpNetworkTransactionTest,
7271 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387272 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347273 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:547274 SessionDependencies session_deps;
7275
7276 HttpRequestInfo request;
7277 request.method = "GET";
7278 request.url = GURL("http://www.google.com/");
7279 request.load_flags = 0;
7280
7281 MockRead data_reads[] = {
7282 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357283 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547284 MockRead("hello world"),
7285 MockRead(true, OK),
7286 };
7287
7288 StaticSocketDataProvider first_transaction(
7289 data_reads, arraysize(data_reads), NULL, 0);
7290 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7291
7292 SSLSocketDataProvider ssl(true, OK);
7293 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357294 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537295 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:547296 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537297 // Make sure we use ssl for spdy here.
7298 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547299
[email protected]2bd93022010-07-17 00:58:447300 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137301 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547302
[email protected]2bd93022010-07-17 00:58:447303 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7304 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547305 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137306 CreateMockRead(*resp),
7307 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547308 MockRead(true, 0, 0),
7309 };
7310
7311 scoped_refptr<DelayedSocketData> spdy_data(
7312 new DelayedSocketData(
7313 1, // wait for one write to finish before reading.
7314 spdy_reads, arraysize(spdy_reads),
7315 spdy_writes, arraysize(spdy_writes)));
7316 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7317
[email protected]f1f3f0f82011-10-01 20:38:107318 TestOldCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:547319
7320 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7321
7322 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7323
[email protected]5a1d7ca2010-04-28 20:12:277324 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547325 EXPECT_EQ(ERR_IO_PENDING, rv);
7326 EXPECT_EQ(OK, callback.WaitForResult());
7327
7328 const HttpResponseInfo* response = trans->GetResponseInfo();
7329 ASSERT_TRUE(response != NULL);
7330 ASSERT_TRUE(response->headers != NULL);
7331 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7332
7333 std::string response_data;
7334 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7335 EXPECT_EQ("hello world", response_data);
7336
7337 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387338 HostPortPair host_port_pair("www.google.com", 443);
7339 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547340 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317341 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287342 scoped_refptr<TransportSocketParams> transport_params(
7343 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:387344
7345 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7346 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287347 connection->Init(host_port_pair.ToString(),
7348 transport_params,
7349 LOWEST,
7350 &callback,
7351 session->transport_socket_pool(),
[email protected]02b0c342010-09-25 21:09:387352 BoundNetLog()));
7353 EXPECT_EQ(OK, callback.WaitForResult());
7354
7355 SSLConfig ssl_config;
7356 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347357 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177358 SSLClientSocketContext context;
7359 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347360 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7361 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177362 NULL /* ssl_host_info */, context));
[email protected]9e1bdd32011-02-03 21:48:347363 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:387364 EXPECT_EQ(OK, callback.WaitForResult());
7365
[email protected]9e1bdd32011-02-03 21:48:347366 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387367 true, OK));
7368
[email protected]2ff8b312010-04-26 22:20:547369 trans.reset(new HttpNetworkTransaction(session));
7370
[email protected]5a1d7ca2010-04-28 20:12:277371 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547372 EXPECT_EQ(ERR_IO_PENDING, rv);
7373 EXPECT_EQ(OK, callback.WaitForResult());
7374
7375 response = trans->GetResponseInfo();
7376 ASSERT_TRUE(response != NULL);
7377 ASSERT_TRUE(response->headers != NULL);
7378 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537379 EXPECT_TRUE(response->was_fetched_via_spdy);
7380 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547381
7382 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7383 EXPECT_EQ("hello!", response_data);
7384
[email protected]5285d972011-10-18 18:56:347385 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387386 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427387}
7388
[email protected]044de0642010-06-17 10:42:157389// GenerateAuthToken is a mighty big test.
7390// It tests all permutation of GenerateAuthToken behavior:
7391// - Synchronous and Asynchronous completion.
7392// - OK or error on completion.
7393// - Direct connection, non-authenticating proxy, and authenticating proxy.
7394// - HTTP or HTTPS backend (to include proxy tunneling).
7395// - Non-authenticating and authenticating backend.
7396//
7397// In all, there are 44 reasonable permuations (for example, if there are
7398// problems generating an auth token for an authenticating proxy, we don't
7399// need to test all permutations of the backend server).
7400//
7401// The test proceeds by going over each of the configuration cases, and
7402// potentially running up to three rounds in each of the tests. The TestConfig
7403// specifies both the configuration for the test as well as the expectations
7404// for the results.
7405TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507406 static const char kServer[] = "http://www.example.com";
7407 static const char kSecureServer[] = "https://www.example.com";
7408 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157409 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7410
7411 enum AuthTiming {
7412 AUTH_NONE,
7413 AUTH_SYNC,
7414 AUTH_ASYNC,
7415 };
7416
7417 const MockWrite kGet(
7418 "GET / HTTP/1.1\r\n"
7419 "Host: www.example.com\r\n"
7420 "Connection: keep-alive\r\n\r\n");
7421 const MockWrite kGetProxy(
7422 "GET http://www.example.com/ HTTP/1.1\r\n"
7423 "Host: www.example.com\r\n"
7424 "Proxy-Connection: keep-alive\r\n\r\n");
7425 const MockWrite kGetAuth(
7426 "GET / HTTP/1.1\r\n"
7427 "Host: www.example.com\r\n"
7428 "Connection: keep-alive\r\n"
7429 "Authorization: auth_token\r\n\r\n");
7430 const MockWrite kGetProxyAuth(
7431 "GET http://www.example.com/ HTTP/1.1\r\n"
7432 "Host: www.example.com\r\n"
7433 "Proxy-Connection: keep-alive\r\n"
7434 "Proxy-Authorization: auth_token\r\n\r\n");
7435 const MockWrite kGetAuthThroughProxy(
7436 "GET http://www.example.com/ HTTP/1.1\r\n"
7437 "Host: www.example.com\r\n"
7438 "Proxy-Connection: keep-alive\r\n"
7439 "Authorization: auth_token\r\n\r\n");
7440 const MockWrite kGetAuthWithProxyAuth(
7441 "GET http://www.example.com/ HTTP/1.1\r\n"
7442 "Host: www.example.com\r\n"
7443 "Proxy-Connection: keep-alive\r\n"
7444 "Proxy-Authorization: auth_token\r\n"
7445 "Authorization: auth_token\r\n\r\n");
7446 const MockWrite kConnect(
7447 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7448 "Host: www.example.com\r\n"
7449 "Proxy-Connection: keep-alive\r\n\r\n");
7450 const MockWrite kConnectProxyAuth(
7451 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7452 "Host: www.example.com\r\n"
7453 "Proxy-Connection: keep-alive\r\n"
7454 "Proxy-Authorization: auth_token\r\n\r\n");
7455
7456 const MockRead kSuccess(
7457 "HTTP/1.1 200 OK\r\n"
7458 "Content-Type: text/html; charset=iso-8859-1\r\n"
7459 "Content-Length: 3\r\n\r\n"
7460 "Yes");
7461 const MockRead kFailure(
7462 "Should not be called.");
7463 const MockRead kServerChallenge(
7464 "HTTP/1.1 401 Unauthorized\r\n"
7465 "WWW-Authenticate: Mock realm=server\r\n"
7466 "Content-Type: text/html; charset=iso-8859-1\r\n"
7467 "Content-Length: 14\r\n\r\n"
7468 "Unauthorized\r\n");
7469 const MockRead kProxyChallenge(
7470 "HTTP/1.1 407 Unauthorized\r\n"
7471 "Proxy-Authenticate: Mock realm=proxy\r\n"
7472 "Proxy-Connection: close\r\n"
7473 "Content-Type: text/html; charset=iso-8859-1\r\n"
7474 "Content-Length: 14\r\n\r\n"
7475 "Unauthorized\r\n");
7476 const MockRead kProxyConnected(
7477 "HTTP/1.1 200 Connection Established\r\n\r\n");
7478
7479 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7480 // no constructors, but the C++ compiler on Windows warns about
7481 // unspecified data in compound literals. So, moved to using constructors,
7482 // and TestRound's created with the default constructor should not be used.
7483 struct TestRound {
7484 TestRound()
7485 : expected_rv(ERR_UNEXPECTED),
7486 extra_write(NULL),
7487 extra_read(NULL) {
7488 }
7489 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7490 int expected_rv_arg)
7491 : write(write_arg),
7492 read(read_arg),
7493 expected_rv(expected_rv_arg),
7494 extra_write(NULL),
7495 extra_read(NULL) {
7496 }
7497 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7498 int expected_rv_arg, const MockWrite* extra_write_arg,
7499 const MockWrite* extra_read_arg)
7500 : write(write_arg),
7501 read(read_arg),
7502 expected_rv(expected_rv_arg),
7503 extra_write(extra_write_arg),
7504 extra_read(extra_read_arg) {
7505 }
7506 MockWrite write;
7507 MockRead read;
7508 int expected_rv;
7509 const MockWrite* extra_write;
7510 const MockRead* extra_read;
7511 };
7512
7513 static const int kNoSSL = 500;
7514
7515 struct TestConfig {
7516 const char* proxy_url;
7517 AuthTiming proxy_auth_timing;
7518 int proxy_auth_rv;
7519 const char* server_url;
7520 AuthTiming server_auth_timing;
7521 int server_auth_rv;
7522 int num_auth_rounds;
7523 int first_ssl_round;
7524 TestRound rounds[3];
7525 } test_configs[] = {
7526 // Non-authenticating HTTP server with a direct connection.
7527 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7528 { TestRound(kGet, kSuccess, OK)}},
7529 // Authenticating HTTP server with a direct connection.
7530 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7531 { TestRound(kGet, kServerChallenge, OK),
7532 TestRound(kGetAuth, kSuccess, OK)}},
7533 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7534 { TestRound(kGet, kServerChallenge, OK),
7535 TestRound(kGetAuth, kFailure, kAuthErr)}},
7536 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7537 { TestRound(kGet, kServerChallenge, OK),
7538 TestRound(kGetAuth, kSuccess, OK)}},
7539 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7540 { TestRound(kGet, kServerChallenge, OK),
7541 TestRound(kGetAuth, kFailure, kAuthErr)}},
7542 // Non-authenticating HTTP server through a non-authenticating proxy.
7543 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7544 { TestRound(kGetProxy, kSuccess, OK)}},
7545 // Authenticating HTTP server through a non-authenticating proxy.
7546 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7547 { TestRound(kGetProxy, kServerChallenge, OK),
7548 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7549 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7550 { TestRound(kGetProxy, kServerChallenge, OK),
7551 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7552 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7553 { TestRound(kGetProxy, kServerChallenge, OK),
7554 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7555 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7556 { TestRound(kGetProxy, kServerChallenge, OK),
7557 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7558 // Non-authenticating HTTP server through an authenticating proxy.
7559 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7560 { TestRound(kGetProxy, kProxyChallenge, OK),
7561 TestRound(kGetProxyAuth, kSuccess, OK)}},
7562 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7563 { TestRound(kGetProxy, kProxyChallenge, OK),
7564 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7565 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7566 { TestRound(kGetProxy, kProxyChallenge, OK),
7567 TestRound(kGetProxyAuth, kSuccess, OK)}},
7568 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7569 { TestRound(kGetProxy, kProxyChallenge, OK),
7570 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7571 // Authenticating HTTP server through an authenticating proxy.
7572 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7573 { TestRound(kGetProxy, kProxyChallenge, OK),
7574 TestRound(kGetProxyAuth, kServerChallenge, OK),
7575 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7576 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7577 { TestRound(kGetProxy, kProxyChallenge, OK),
7578 TestRound(kGetProxyAuth, kServerChallenge, OK),
7579 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7580 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7581 { TestRound(kGetProxy, kProxyChallenge, OK),
7582 TestRound(kGetProxyAuth, kServerChallenge, OK),
7583 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7584 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7585 { TestRound(kGetProxy, kProxyChallenge, OK),
7586 TestRound(kGetProxyAuth, kServerChallenge, OK),
7587 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7588 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7589 { TestRound(kGetProxy, kProxyChallenge, OK),
7590 TestRound(kGetProxyAuth, kServerChallenge, OK),
7591 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7592 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7593 { TestRound(kGetProxy, kProxyChallenge, OK),
7594 TestRound(kGetProxyAuth, kServerChallenge, OK),
7595 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7596 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7597 { TestRound(kGetProxy, kProxyChallenge, OK),
7598 TestRound(kGetProxyAuth, kServerChallenge, OK),
7599 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7600 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7601 { TestRound(kGetProxy, kProxyChallenge, OK),
7602 TestRound(kGetProxyAuth, kServerChallenge, OK),
7603 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7604 // Non-authenticating HTTPS server with a direct connection.
7605 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7606 { TestRound(kGet, kSuccess, OK)}},
7607 // Authenticating HTTPS server with a direct connection.
7608 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7609 { TestRound(kGet, kServerChallenge, OK),
7610 TestRound(kGetAuth, kSuccess, OK)}},
7611 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7612 { TestRound(kGet, kServerChallenge, OK),
7613 TestRound(kGetAuth, kFailure, kAuthErr)}},
7614 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7615 { TestRound(kGet, kServerChallenge, OK),
7616 TestRound(kGetAuth, kSuccess, OK)}},
7617 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7618 { TestRound(kGet, kServerChallenge, OK),
7619 TestRound(kGetAuth, kFailure, kAuthErr)}},
7620 // Non-authenticating HTTPS server with a non-authenticating proxy.
7621 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7622 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7623 // Authenticating HTTPS server through a non-authenticating proxy.
7624 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7625 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7626 TestRound(kGetAuth, kSuccess, OK)}},
7627 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7628 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7629 TestRound(kGetAuth, kFailure, kAuthErr)}},
7630 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7631 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7632 TestRound(kGetAuth, kSuccess, OK)}},
7633 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7634 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7635 TestRound(kGetAuth, kFailure, kAuthErr)}},
7636 // Non-Authenticating HTTPS server through an authenticating proxy.
7637 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7638 { TestRound(kConnect, kProxyChallenge, OK),
7639 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7640 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7641 { TestRound(kConnect, kProxyChallenge, OK),
7642 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7643 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7644 { TestRound(kConnect, kProxyChallenge, OK),
7645 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7646 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7647 { TestRound(kConnect, kProxyChallenge, OK),
7648 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7649 // Authenticating HTTPS server through an authenticating proxy.
7650 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7651 { TestRound(kConnect, kProxyChallenge, OK),
7652 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7653 &kGet, &kServerChallenge),
7654 TestRound(kGetAuth, kSuccess, OK)}},
7655 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7656 { TestRound(kConnect, kProxyChallenge, OK),
7657 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7658 &kGet, &kServerChallenge),
7659 TestRound(kGetAuth, kFailure, kAuthErr)}},
7660 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7661 { TestRound(kConnect, kProxyChallenge, OK),
7662 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7663 &kGet, &kServerChallenge),
7664 TestRound(kGetAuth, kSuccess, OK)}},
7665 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7666 { TestRound(kConnect, kProxyChallenge, OK),
7667 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7668 &kGet, &kServerChallenge),
7669 TestRound(kGetAuth, kFailure, kAuthErr)}},
7670 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7671 { TestRound(kConnect, kProxyChallenge, OK),
7672 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7673 &kGet, &kServerChallenge),
7674 TestRound(kGetAuth, kSuccess, OK)}},
7675 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7676 { TestRound(kConnect, kProxyChallenge, OK),
7677 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7678 &kGet, &kServerChallenge),
7679 TestRound(kGetAuth, kFailure, kAuthErr)}},
7680 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7681 { TestRound(kConnect, kProxyChallenge, OK),
7682 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7683 &kGet, &kServerChallenge),
7684 TestRound(kGetAuth, kSuccess, OK)}},
7685 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7686 { TestRound(kConnect, kProxyChallenge, OK),
7687 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7688 &kGet, &kServerChallenge),
7689 TestRound(kGetAuth, kFailure, kAuthErr)}},
7690 };
7691
7692 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157693 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087694 HttpAuthHandlerMock::Factory* auth_factory(
7695 new HttpAuthHandlerMock::Factory());
7696 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157697 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267698
7699 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157700 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087701 for (int n = 0; n < 2; n++) {
7702 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7703 std::string auth_challenge = "Mock realm=proxy";
7704 GURL origin(test_config.proxy_url);
7705 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7706 auth_challenge.end());
7707 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7708 origin, BoundNetLog());
7709 auth_handler->SetGenerateExpectation(
7710 test_config.proxy_auth_timing == AUTH_ASYNC,
7711 test_config.proxy_auth_rv);
7712 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7713 }
[email protected]044de0642010-06-17 10:42:157714 }
7715 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007716 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157717 std::string auth_challenge = "Mock realm=server";
7718 GURL origin(test_config.server_url);
7719 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7720 auth_challenge.end());
7721 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7722 origin, BoundNetLog());
7723 auth_handler->SetGenerateExpectation(
7724 test_config.server_auth_timing == AUTH_ASYNC,
7725 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087726 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157727 }
7728 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127729 session_deps.proxy_service.reset(
7730 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157731 } else {
[email protected]6104ea5d2011-04-27 21:37:127732 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157733 }
7734
7735 HttpRequestInfo request;
7736 request.method = "GET";
7737 request.url = GURL(test_config.server_url);
7738 request.load_flags = 0;
7739
[email protected]0b0bf032010-09-21 18:08:507740 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7741 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157742
7743 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7744 const TestRound& read_write_round = test_config.rounds[round];
7745
7746 // Set up expected reads and writes.
7747 MockRead reads[2];
7748 reads[0] = read_write_round.read;
7749 size_t length_reads = 1;
7750 if (read_write_round.extra_read) {
7751 reads[1] = *read_write_round.extra_read;
7752 length_reads = 2;
7753 }
7754
7755 MockWrite writes[2];
7756 writes[0] = read_write_round.write;
7757 size_t length_writes = 1;
7758 if (read_write_round.extra_write) {
7759 writes[1] = *read_write_round.extra_write;
7760 length_writes = 2;
7761 }
7762 StaticSocketDataProvider data_provider(
7763 reads, length_reads, writes, length_writes);
7764 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7765
7766 // Add an SSL sequence if necessary.
7767 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7768 if (round >= test_config.first_ssl_round)
7769 session_deps.socket_factory.AddSSLSocketDataProvider(
7770 &ssl_socket_data_provider);
7771
7772 // Start or restart the transaction.
[email protected]f1f3f0f82011-10-01 20:38:107773 TestOldCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:157774 int rv;
7775 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507776 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157777 } else {
[email protected]f3cf9802011-10-28 18:44:587778 rv = trans.RestartWithAuth(AuthCredentials(kFoo, kBar), &callback);
[email protected]044de0642010-06-17 10:42:157779 }
7780 if (rv == ERR_IO_PENDING)
7781 rv = callback.WaitForResult();
7782
7783 // Compare results with expected data.
7784 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507785 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157786 if (read_write_round.expected_rv == OK) {
[email protected]fe2255a2011-09-20 19:37:507787 ASSERT_TRUE(response != NULL);
[email protected]044de0642010-06-17 10:42:157788 } else {
7789 EXPECT_TRUE(response == NULL);
7790 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7791 continue;
7792 }
7793 if (round + 1 < test_config.num_auth_rounds) {
7794 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7795 } else {
7796 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7797 }
7798 }
[email protected]e5ae96a2010-04-14 20:12:457799 }
7800}
7801
[email protected]c871bce92010-07-15 21:51:147802TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7803 // Do multi-round authentication and make sure it works correctly.
7804 SessionDependencies session_deps;
7805 HttpAuthHandlerMock::Factory* auth_factory(
7806 new HttpAuthHandlerMock::Factory());
7807 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127808 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147809 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7810 session_deps.host_resolver->set_synchronous_mode(true);
7811
7812 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7813 auth_handler->set_connection_based(true);
7814 std::string auth_challenge = "Mock realm=server";
7815 GURL origin("http://www.example.com");
7816 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7817 auth_challenge.end());
7818 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7819 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087820 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147821
[email protected]c871bce92010-07-15 21:51:147822 int rv = OK;
7823 const HttpResponseInfo* response = NULL;
7824 HttpRequestInfo request;
7825 request.method = "GET";
7826 request.url = origin;
7827 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277828
7829 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107830
7831 // Use a TCP Socket Pool with only one connection per group. This is used
7832 // to validate that the TCP socket is not released to the pool between
7833 // each round of multi-round authentication.
7834 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287835 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7836 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107837 50, // Max sockets for pool
7838 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287839 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107840 session_deps.host_resolver.get(),
7841 &session_deps.socket_factory,
7842 session_deps.net_log);
[email protected]ab739042011-04-07 15:22:287843 session_peer.SetTransportSocketPool(transport_pool);
[email protected]7ef4cbbb2011-02-06 11:19:107844
[email protected]cb9bf6ca2011-01-28 13:15:277845 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:107846 TestOldCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:147847
7848 const MockWrite kGet(
7849 "GET / HTTP/1.1\r\n"
7850 "Host: www.example.com\r\n"
7851 "Connection: keep-alive\r\n\r\n");
7852 const MockWrite kGetAuth(
7853 "GET / HTTP/1.1\r\n"
7854 "Host: www.example.com\r\n"
7855 "Connection: keep-alive\r\n"
7856 "Authorization: auth_token\r\n\r\n");
7857
7858 const MockRead kServerChallenge(
7859 "HTTP/1.1 401 Unauthorized\r\n"
7860 "WWW-Authenticate: Mock realm=server\r\n"
7861 "Content-Type: text/html; charset=iso-8859-1\r\n"
7862 "Content-Length: 14\r\n\r\n"
7863 "Unauthorized\r\n");
7864 const MockRead kSuccess(
7865 "HTTP/1.1 200 OK\r\n"
7866 "Content-Type: text/html; charset=iso-8859-1\r\n"
7867 "Content-Length: 3\r\n\r\n"
7868 "Yes");
7869
7870 MockWrite writes[] = {
7871 // First round
7872 kGet,
7873 // Second round
7874 kGetAuth,
7875 // Third round
7876 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307877 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107878 kGetAuth,
7879 // Competing request
7880 kGet,
[email protected]c871bce92010-07-15 21:51:147881 };
7882 MockRead reads[] = {
7883 // First round
7884 kServerChallenge,
7885 // Second round
7886 kServerChallenge,
7887 // Third round
[email protected]eca50e122010-09-11 14:03:307888 kServerChallenge,
7889 // Fourth round
[email protected]c871bce92010-07-15 21:51:147890 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107891 // Competing response
7892 kSuccess,
[email protected]c871bce92010-07-15 21:51:147893 };
7894 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7895 writes, arraysize(writes));
7896 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7897
[email protected]7ef4cbbb2011-02-06 11:19:107898 const char* const kSocketGroup = "www.example.com:80";
7899
7900 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147901 auth_handler->SetGenerateExpectation(false, OK);
7902 rv = trans->Start(&request, &callback, BoundNetLog());
7903 if (rv == ERR_IO_PENDING)
7904 rv = callback.WaitForResult();
7905 EXPECT_EQ(OK, rv);
7906 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507907 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147908 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287909 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147910
[email protected]7ef4cbbb2011-02-06 11:19:107911 // In between rounds, another request comes in for the same domain.
7912 // It should not be able to grab the TCP socket that trans has already
7913 // claimed.
7914 scoped_ptr<HttpTransaction> trans_compete(
7915 new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:107916 TestOldCompletionCallback callback_compete;
[email protected]7ef4cbbb2011-02-06 11:19:107917 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7918 EXPECT_EQ(ERR_IO_PENDING, rv);
7919 // callback_compete.WaitForResult at this point would stall forever,
7920 // since the HttpNetworkTransaction does not release the request back to
7921 // the pool until after authentication completes.
7922
7923 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147924 auth_handler->SetGenerateExpectation(false, OK);
[email protected]f3cf9802011-10-28 18:44:587925 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback);
[email protected]c871bce92010-07-15 21:51:147926 if (rv == ERR_IO_PENDING)
7927 rv = callback.WaitForResult();
7928 EXPECT_EQ(OK, rv);
7929 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507930 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147931 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287932 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147933
[email protected]7ef4cbbb2011-02-06 11:19:107934 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147935 auth_handler->SetGenerateExpectation(false, OK);
[email protected]f3cf9802011-10-28 18:44:587936 rv = trans->RestartWithAuth(AuthCredentials(), &callback);
[email protected]c871bce92010-07-15 21:51:147937 if (rv == ERR_IO_PENDING)
7938 rv = callback.WaitForResult();
7939 EXPECT_EQ(OK, rv);
7940 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507941 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147942 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287943 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307944
[email protected]7ef4cbbb2011-02-06 11:19:107945 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307946 auth_handler->SetGenerateExpectation(false, OK);
[email protected]f3cf9802011-10-28 18:44:587947 rv = trans->RestartWithAuth(AuthCredentials(), &callback);
[email protected]eca50e122010-09-11 14:03:307948 if (rv == ERR_IO_PENDING)
7949 rv = callback.WaitForResult();
7950 EXPECT_EQ(OK, rv);
7951 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507952 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:307953 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287954 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107955
7956 // Read the body since the fourth round was successful. This will also
7957 // release the socket back to the pool.
7958 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7959 rv = trans->Read(io_buf, io_buf->size(), &callback);
7960 if (rv == ERR_IO_PENDING)
7961 rv = callback.WaitForResult();
7962 EXPECT_EQ(3, rv);
7963 rv = trans->Read(io_buf, io_buf->size(), &callback);
7964 EXPECT_EQ(0, rv);
7965 // There are still 0 idle sockets, since the trans_compete transaction
7966 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287967 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107968
7969 // The competing request can now finish. Wait for the headers and then
7970 // read the body.
7971 rv = callback_compete.WaitForResult();
7972 EXPECT_EQ(OK, rv);
7973 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7974 if (rv == ERR_IO_PENDING)
7975 rv = callback.WaitForResult();
7976 EXPECT_EQ(3, rv);
7977 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7978 EXPECT_EQ(0, rv);
7979
7980 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287981 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147982}
7983
[email protected]aeaca1f2010-04-20 22:05:217984class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7985 public:
[email protected]06650c52010-06-03 00:49:177986 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217987 : fail_all_(fail_all) {
7988 }
7989
7990 virtual MockRead GetNextRead() {
7991 if (fail_all_)
7992 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7993
7994 return MockRead(false /* async */,
7995 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7996 }
7997
7998 virtual MockWriteResult OnWrite(const std::string& data) {
7999 return MockWriteResult(false /* async */, data.size());
8000 }
8001
8002 void Reset() {
8003 }
8004
8005 private:
8006 const bool fail_all_;
8007};
8008
8009// Test that we restart a connection when we see a decompression failure from
8010// the peer during the handshake. (In the real world we'll restart with SSLv3
8011// and we won't offer DEFLATE in that case.)
8012TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
8013 HttpRequestInfo request;
8014 request.method = "GET";
8015 request.url = GURL("https://tlsdecompressionfailure.example.com/");
8016 request.load_flags = 0;
8017
8018 SessionDependencies session_deps;
8019 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8020 false /* fail all reads */);
8021 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8022 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:118023 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:218024 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
8025 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8026 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8027 session_deps.socket_factory.AddSSLSocketDataProvider(
8028 &ssl_socket_data_provider1);
8029 session_deps.socket_factory.AddSSLSocketDataProvider(
8030 &ssl_socket_data_provider2);
8031
[email protected]e60e47a2010-07-14 03:37:188032 // Work around http://crbug.com/37454
8033 StaticSocketDataProvider bug37454_connection;
8034 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
8035 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
8036
[email protected]aeaca1f2010-04-20 22:05:218037 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8038 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:108039 TestOldCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218040
[email protected]5a1d7ca2010-04-28 20:12:278041 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218042 EXPECT_EQ(ERR_IO_PENDING, rv);
8043 EXPECT_EQ(OK, callback.WaitForResult());
8044
8045 const HttpResponseInfo* response = trans->GetResponseInfo();
8046 ASSERT_TRUE(response != NULL);
8047 ASSERT_TRUE(response->headers != NULL);
8048 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8049
8050 std::string response_data;
8051 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8052 EXPECT_EQ("ok.", response_data);
8053}
8054
8055// Test that we restart a connection if we get a decompression failure from the
8056// peer while reading the first bytes from the connection. This occurs when the
8057// peer cannot handle DEFLATE but we're using False Start, so we don't notice
8058// in the handshake.
8059TEST_F(HttpNetworkTransactionTest,
8060 RestartAfterTLSDecompressionFailureWithFalseStart) {
8061 HttpRequestInfo request;
8062 request.method = "GET";
8063 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
8064 request.load_flags = 0;
8065
8066 SessionDependencies session_deps;
8067 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8068 true /* fail all reads */);
8069 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8070 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
8071 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
8072 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8073 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8074 session_deps.socket_factory.AddSSLSocketDataProvider(
8075 &ssl_socket_data_provider1);
8076 session_deps.socket_factory.AddSSLSocketDataProvider(
8077 &ssl_socket_data_provider2);
8078
8079 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8080 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:108081 TestOldCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218082
[email protected]5a1d7ca2010-04-28 20:12:278083 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218084 EXPECT_EQ(ERR_IO_PENDING, rv);
8085 EXPECT_EQ(OK, callback.WaitForResult());
8086
8087 const HttpResponseInfo* response = trans->GetResponseInfo();
8088 ASSERT_TRUE(response != NULL);
8089 ASSERT_TRUE(response->headers != NULL);
8090 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8091
8092 std::string response_data;
8093 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8094 EXPECT_EQ("ok.", response_data);
8095}
8096
[email protected]65041fa2010-05-21 06:56:538097// This tests the case that a request is issued via http instead of spdy after
8098// npn is negotiated.
8099TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:388100 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348101 HttpStreamFactory::set_next_protos(
8102 MakeNextProtos("http/1.1", "http1.1", NULL));
[email protected]65041fa2010-05-21 06:56:538103 SessionDependencies session_deps;
8104 HttpRequestInfo request;
8105 request.method = "GET";
8106 request.url = GURL("https://www.google.com/");
8107 request.load_flags = 0;
8108
8109 MockWrite data_writes[] = {
8110 MockWrite("GET / HTTP/1.1\r\n"
8111 "Host: www.google.com\r\n"
8112 "Connection: keep-alive\r\n\r\n"),
8113 };
8114
8115 MockRead data_reads[] = {
8116 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:358117 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:538118 MockRead("hello world"),
8119 MockRead(false, OK),
8120 };
8121
8122 SSLSocketDataProvider ssl(true, OK);
8123 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8124 ssl.next_proto = "http/1.1";
8125
8126 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8127
8128 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8129 data_writes, arraysize(data_writes));
8130 session_deps.socket_factory.AddSocketDataProvider(&data);
8131
[email protected]f1f3f0f82011-10-01 20:38:108132 TestOldCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:538133
8134 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8135 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8136
8137 int rv = trans->Start(&request, &callback, BoundNetLog());
8138
8139 EXPECT_EQ(ERR_IO_PENDING, rv);
8140 EXPECT_EQ(OK, callback.WaitForResult());
8141
8142 const HttpResponseInfo* response = trans->GetResponseInfo();
8143 ASSERT_TRUE(response != NULL);
8144 ASSERT_TRUE(response->headers != NULL);
8145 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8146
8147 std::string response_data;
8148 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8149 EXPECT_EQ("hello world", response_data);
8150
8151 EXPECT_FALSE(response->was_fetched_via_spdy);
8152 EXPECT_TRUE(response->was_npn_negotiated);
8153
[email protected]5285d972011-10-18 18:56:348154 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388155 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:538156}
[email protected]26ef6582010-06-24 02:30:478157
8158TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8159 // Simulate the SSL handshake completing with an NPN negotiation
8160 // followed by an immediate server closing of the socket.
8161 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:388162 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348163 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]26ef6582010-06-24 02:30:478164 SessionDependencies session_deps;
8165
8166 HttpRequestInfo request;
8167 request.method = "GET";
8168 request.url = GURL("https://www.google.com/");
8169 request.load_flags = 0;
8170
8171 SSLSocketDataProvider ssl(true, OK);
8172 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:358173 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:478174 ssl.was_npn_negotiated = true;
8175 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8176
[email protected]2bd93022010-07-17 00:58:448177 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:138178 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:478179
8180 MockRead spdy_reads[] = {
8181 MockRead(false, 0, 0) // Not async - return 0 immediately.
8182 };
8183
8184 scoped_refptr<DelayedSocketData> spdy_data(
8185 new DelayedSocketData(
8186 0, // don't wait in this case, immediate hangup.
8187 spdy_reads, arraysize(spdy_reads),
8188 spdy_writes, arraysize(spdy_writes)));
8189 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8190
[email protected]f1f3f0f82011-10-01 20:38:108191 TestOldCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:478192
8193 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8194 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8195
8196 int rv = trans->Start(&request, &callback, BoundNetLog());
8197 EXPECT_EQ(ERR_IO_PENDING, rv);
8198 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8199
[email protected]5285d972011-10-18 18:56:348200 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388201 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:478202}
[email protected]65d34382010-07-01 18:12:268203
[email protected]f45c1ee2010-08-03 00:54:308204TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8205 // This test ensures that the URL passed into the proxy is upgraded
8206 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:388207 HttpStreamFactory::set_use_alternate_protocols(true);
8208 HttpStreamFactory::set_next_protos(
[email protected]5285d972011-10-18 18:56:348209 MakeNextProtos("http/1.1", "http1.1", "spdy/2", "spdy", NULL));
[email protected]f45c1ee2010-08-03 00:54:308210
[email protected]81cdfcd2010-10-16 00:49:008211 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:308212 HttpAuthHandlerMock::Factory* auth_factory =
8213 new HttpAuthHandlerMock::Factory();
8214 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
[email protected]2d01c262011-08-11 23:07:088215 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:308216 auth_factory->set_do_init_from_challenge(true);
8217 session_deps.http_auth_handler_factory.reset(auth_factory);
8218
8219 HttpRequestInfo request;
8220 request.method = "GET";
8221 request.url = GURL("http://www.google.com");
8222 request.load_flags = 0;
8223
8224 // First round goes unauthenticated through the proxy.
8225 MockWrite data_writes_1[] = {
8226 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8227 "Host: www.google.com\r\n"
8228 "Proxy-Connection: keep-alive\r\n"
8229 "\r\n"),
8230 };
8231 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:598232 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:308233 MockRead("HTTP/1.1 200 OK\r\n"
8234 "Alternate-Protocol: 443:npn-spdy/2\r\n"
8235 "Proxy-Connection: close\r\n"
8236 "\r\n"),
8237 };
8238 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8239 data_writes_1, arraysize(data_writes_1));
8240
8241 // Second round tries to tunnel to www.google.com due to the
8242 // Alternate-Protocol announcement in the first round. It fails due
8243 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:598244 // After the failure, a tunnel is established to www.google.com using
8245 // Proxy-Authorization headers. There is then a SPDY request round.
8246 //
8247 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8248 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8249 // does a Disconnect and Connect on the same socket, rather than trying
8250 // to obtain a new one.
8251 //
8252 // NOTE: Originally, the proxy response to the second CONNECT request
8253 // simply returned another 407 so the unit test could skip the SSL connection
8254 // establishment and SPDY framing issues. Alas, the
8255 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308256 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598257
[email protected]f45c1ee2010-08-03 00:54:308258 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8259 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8260 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8261
[email protected]394816e92010-08-03 07:38:598262 MockWrite data_writes_2[] = {
8263 // First connection attempt without Proxy-Authorization.
8264 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8265 "Host: www.google.com\r\n"
8266 "Proxy-Connection: keep-alive\r\n"
8267 "\r\n"),
8268
8269 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308270 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8271 "Host: www.google.com\r\n"
8272 "Proxy-Connection: keep-alive\r\n"
8273 "Proxy-Authorization: auth_token\r\n"
8274 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308275
[email protected]394816e92010-08-03 07:38:598276 // SPDY request
8277 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308278 };
[email protected]394816e92010-08-03 07:38:598279 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8280 "Proxy-Authenticate: Mock\r\n"
8281 "Proxy-Connection: close\r\n"
8282 "\r\n");
8283 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8284 MockRead data_reads_2[] = {
8285 // First connection attempt fails
8286 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8287 MockRead(true, kRejectConnectResponse,
8288 arraysize(kRejectConnectResponse) - 1, 1),
8289
8290 // Second connection attempt passes
8291 MockRead(true, kAcceptConnectResponse,
8292 arraysize(kAcceptConnectResponse) -1, 4),
8293
8294 // SPDY response
8295 CreateMockRead(*resp.get(), 6),
8296 CreateMockRead(*data.get(), 6),
8297 MockRead(true, 0, 0, 6),
8298 };
8299 scoped_refptr<OrderedSocketData> data_2(
8300 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8301 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308302
8303 SSLSocketDataProvider ssl(true, OK);
8304 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8305 ssl.next_proto = "spdy/2";
8306 ssl.was_npn_negotiated = true;
8307
[email protected]2d6728692011-03-12 01:39:558308 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8309 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8310 NULL, 0, NULL, 0);
8311 hanging_non_alternate_protocol_socket.set_connect_data(
8312 never_finishing_connect);
8313
[email protected]f45c1ee2010-08-03 00:54:308314 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598315 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308316 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558317 session_deps.socket_factory.AddSocketDataProvider(
8318 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308319 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8320
8321 // First round should work and provide the Alternate-Protocol state.
[email protected]f1f3f0f82011-10-01 20:38:108322 TestOldCompletionCallback callback_1;
[email protected]f45c1ee2010-08-03 00:54:308323 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8324 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8325 EXPECT_EQ(ERR_IO_PENDING, rv);
8326 EXPECT_EQ(OK, callback_1.WaitForResult());
8327
8328 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]f1f3f0f82011-10-01 20:38:108329 TestOldCompletionCallback callback_2;
[email protected]f45c1ee2010-08-03 00:54:308330 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8331 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8332 EXPECT_EQ(ERR_IO_PENDING, rv);
8333 EXPECT_EQ(OK, callback_2.WaitForResult());
8334 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508335 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:308336 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8337
8338 // Restart with auth. Tunnel should work and response received.
[email protected]f1f3f0f82011-10-01 20:38:108339 TestOldCompletionCallback callback_3;
[email protected]f3cf9802011-10-28 18:44:588340 rv = trans_2->RestartWithAuth(AuthCredentials(kFoo, kBar), &callback_3);
[email protected]f45c1ee2010-08-03 00:54:308341 EXPECT_EQ(ERR_IO_PENDING, rv);
8342 EXPECT_EQ(OK, callback_3.WaitForResult());
8343
8344 // After all that work, these two lines (or actually, just the scheme) are
8345 // what this test is all about. Make sure it happens correctly.
8346 const GURL& request_url = auth_handler->request_url();
8347 EXPECT_EQ("https", request_url.scheme());
8348 EXPECT_EQ("www.google.com", request_url.host());
8349
[email protected]5285d972011-10-18 18:56:348350 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388351 HttpStreamFactory::set_use_alternate_protocols(false);
8352}
8353
8354// Test that if we cancel the transaction as the connection is completing, that
8355// everything tears down correctly.
8356TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8357 // Setup everything about the connection to complete synchronously, so that
8358 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8359 // for is the callback from the HttpStreamRequest.
8360 // Then cancel the transaction.
8361 // Verify that we don't crash.
8362 MockConnect mock_connect(false, OK);
8363 MockRead data_reads[] = {
8364 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8365 MockRead(false, "hello world"),
8366 MockRead(false, OK),
8367 };
8368
[email protected]8e6441ca2010-08-19 05:56:388369 HttpRequestInfo request;
8370 request.method = "GET";
8371 request.url = GURL("http://www.google.com/");
8372 request.load_flags = 0;
8373
[email protected]cb9bf6ca2011-01-28 13:15:278374 SessionDependencies session_deps;
8375 session_deps.host_resolver->set_synchronous_mode(true);
8376 scoped_ptr<HttpTransaction> trans(
8377 new HttpNetworkTransaction(CreateSession(&session_deps)));
8378
[email protected]8e6441ca2010-08-19 05:56:388379 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8380 data.set_connect_data(mock_connect);
8381 session_deps.socket_factory.AddSocketDataProvider(&data);
8382
[email protected]f1f3f0f82011-10-01 20:38:108383 TestOldCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:388384
8385 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8386 int rv = trans->Start(&request, &callback, log.bound());
8387 EXPECT_EQ(ERR_IO_PENDING, rv);
8388 trans.reset(); // Cancel the transaction here.
8389
8390 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308391}
8392
[email protected]76a505b2010-08-25 06:23:008393// Test a basic GET request through a proxy.
8394TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008395 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008396 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8397 session_deps.net_log = log.bound().net_log();
8398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8399
[email protected]76a505b2010-08-25 06:23:008400 HttpRequestInfo request;
8401 request.method = "GET";
8402 request.url = GURL("http://www.google.com/");
8403
8404 MockWrite data_writes1[] = {
8405 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8406 "Host: www.google.com\r\n"
8407 "Proxy-Connection: keep-alive\r\n\r\n"),
8408 };
8409
8410 MockRead data_reads1[] = {
8411 MockRead("HTTP/1.1 200 OK\r\n"),
8412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8413 MockRead("Content-Length: 100\r\n\r\n"),
8414 MockRead(false, OK),
8415 };
8416
8417 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8418 data_writes1, arraysize(data_writes1));
8419 session_deps.socket_factory.AddSocketDataProvider(&data1);
8420
[email protected]f1f3f0f82011-10-01 20:38:108421 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008422
[email protected]0b0bf032010-09-21 18:08:508423 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8424
[email protected]76a505b2010-08-25 06:23:008425 int rv = trans->Start(&request, &callback1, log.bound());
8426 EXPECT_EQ(ERR_IO_PENDING, rv);
8427
8428 rv = callback1.WaitForResult();
8429 EXPECT_EQ(OK, rv);
8430
8431 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508432 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008433
8434 EXPECT_TRUE(response->headers->IsKeepAlive());
8435 EXPECT_EQ(200, response->headers->response_code());
8436 EXPECT_EQ(100, response->headers->GetContentLength());
8437 EXPECT_TRUE(response->was_fetched_via_proxy);
8438 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8439}
8440
8441// Test a basic HTTPS GET request through a proxy.
8442TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008443 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008444 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8445 session_deps.net_log = log.bound().net_log();
8446 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8447
[email protected]76a505b2010-08-25 06:23:008448 HttpRequestInfo request;
8449 request.method = "GET";
8450 request.url = GURL("https://www.google.com/");
8451
8452 // Since we have proxy, should try to establish tunnel.
8453 MockWrite data_writes1[] = {
8454 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8455 "Host: www.google.com\r\n"
8456 "Proxy-Connection: keep-alive\r\n\r\n"),
8457
8458 MockWrite("GET / HTTP/1.1\r\n"
8459 "Host: www.google.com\r\n"
8460 "Connection: keep-alive\r\n\r\n"),
8461 };
8462
8463 MockRead data_reads1[] = {
8464 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8465
8466 MockRead("HTTP/1.1 200 OK\r\n"),
8467 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8468 MockRead("Content-Length: 100\r\n\r\n"),
8469 MockRead(false, OK),
8470 };
8471
8472 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8473 data_writes1, arraysize(data_writes1));
8474 session_deps.socket_factory.AddSocketDataProvider(&data1);
8475 SSLSocketDataProvider ssl(true, OK);
8476 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8477
[email protected]f1f3f0f82011-10-01 20:38:108478 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008479
[email protected]0b0bf032010-09-21 18:08:508480 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8481
[email protected]76a505b2010-08-25 06:23:008482 int rv = trans->Start(&request, &callback1, log.bound());
8483 EXPECT_EQ(ERR_IO_PENDING, rv);
8484
8485 rv = callback1.WaitForResult();
8486 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408487 net::CapturingNetLog::EntryList entries;
8488 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008489 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408490 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008491 NetLog::PHASE_NONE);
8492 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408493 entries, pos,
[email protected]76a505b2010-08-25 06:23:008494 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8495 NetLog::PHASE_NONE);
8496
8497 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508498 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008499
8500 EXPECT_TRUE(response->headers->IsKeepAlive());
8501 EXPECT_EQ(200, response->headers->response_code());
8502 EXPECT_EQ(100, response->headers->GetContentLength());
8503 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8504 EXPECT_TRUE(response->was_fetched_via_proxy);
8505}
8506
8507// Test a basic HTTPS GET request through a proxy, but the server hangs up
8508// while establishing the tunnel.
8509TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008510 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008511 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8512 session_deps.net_log = log.bound().net_log();
8513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8514
[email protected]76a505b2010-08-25 06:23:008515 HttpRequestInfo request;
8516 request.method = "GET";
8517 request.url = GURL("https://www.google.com/");
8518
8519 // Since we have proxy, should try to establish tunnel.
8520 MockWrite data_writes1[] = {
8521 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8522 "Host: www.google.com\r\n"
8523 "Proxy-Connection: keep-alive\r\n\r\n"),
8524
8525 MockWrite("GET / HTTP/1.1\r\n"
8526 "Host: www.google.com\r\n"
8527 "Connection: keep-alive\r\n\r\n"),
8528 };
8529
8530 MockRead data_reads1[] = {
8531 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8532 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8533 MockRead(true, 0, 0), // EOF
8534 };
8535
8536 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8537 data_writes1, arraysize(data_writes1));
8538 session_deps.socket_factory.AddSocketDataProvider(&data1);
8539 SSLSocketDataProvider ssl(true, OK);
8540 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8541
[email protected]f1f3f0f82011-10-01 20:38:108542 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008543
[email protected]0b0bf032010-09-21 18:08:508544 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8545
[email protected]76a505b2010-08-25 06:23:008546 int rv = trans->Start(&request, &callback1, log.bound());
8547 EXPECT_EQ(ERR_IO_PENDING, rv);
8548
8549 rv = callback1.WaitForResult();
8550 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408551 net::CapturingNetLog::EntryList entries;
8552 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008553 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408554 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008555 NetLog::PHASE_NONE);
8556 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408557 entries, pos,
[email protected]76a505b2010-08-25 06:23:008558 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8559 NetLog::PHASE_NONE);
8560}
8561
[email protected]749eefa82010-09-13 22:14:038562// Test for crbug.com/55424.
8563TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8564 SessionDependencies session_deps;
8565
8566 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8567 "https://www.google.com", false, 1, LOWEST));
8568 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8569
8570 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8571 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8572 MockRead spdy_reads[] = {
8573 CreateMockRead(*resp),
8574 CreateMockRead(*data),
8575 MockRead(true, 0, 0),
8576 };
8577
8578 scoped_refptr<DelayedSocketData> spdy_data(
8579 new DelayedSocketData(
8580 1, // wait for one write to finish before reading.
8581 spdy_reads, arraysize(spdy_reads),
8582 spdy_writes, arraysize(spdy_writes)));
8583 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8584
8585 SSLSocketDataProvider ssl(true, OK);
8586 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8587 ssl.next_proto = "spdy/2";
8588 ssl.was_npn_negotiated = true;
8589 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8590
8591 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8592
8593 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388594 HostPortPair host_port_pair("www.google.com", 443);
8595 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038596 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318597 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288598 scoped_refptr<TransportSocketParams> transport_params(
8599 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]f1f3f0f82011-10-01 20:38:108600 TestOldCompletionCallback callback;
[email protected]02b0c342010-09-25 21:09:388601
8602 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8603 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288604 connection->Init(host_port_pair.ToString(), transport_params,
8605 LOWEST, &callback,
8606 session->transport_socket_pool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388607 EXPECT_EQ(OK, callback.WaitForResult());
8608 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038609
8610 HttpRequestInfo request;
8611 request.method = "GET";
8612 request.url = GURL("https://www.google.com/");
8613 request.load_flags = 0;
8614
8615 // This is the important line that marks this as a preconnect.
8616 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8617
8618 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8619
[email protected]749eefa82010-09-13 22:14:038620 int rv = trans->Start(&request, &callback, BoundNetLog());
8621 EXPECT_EQ(ERR_IO_PENDING, rv);
8622 EXPECT_EQ(OK, callback.WaitForResult());
8623}
8624
[email protected]73b8dd222010-11-11 19:55:248625// Given a net error, cause that error to be returned from the first Write()
8626// call and verify that the HttpTransaction fails with that error.
8627static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278628 net::HttpRequestInfo request_info;
8629 request_info.url = GURL("https://www.example.com/");
8630 request_info.method = "GET";
8631 request_info.load_flags = net::LOAD_NORMAL;
8632
[email protected]73b8dd222010-11-11 19:55:248633 SessionDependencies session_deps;
8634
8635 SSLSocketDataProvider ssl_data(async, OK);
8636 net::MockWrite data_writes[] = {
8637 net::MockWrite(async, error),
8638 };
8639 net::StaticSocketDataProvider data(NULL, 0,
8640 data_writes, arraysize(data_writes));
8641 session_deps.socket_factory.AddSocketDataProvider(&data);
8642 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8643
8644 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8645 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8646
[email protected]f1f3f0f82011-10-01 20:38:108647 TestOldCompletionCallback callback;
[email protected]73b8dd222010-11-11 19:55:248648 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8649 if (rv == net::ERR_IO_PENDING)
8650 rv = callback.WaitForResult();
8651 ASSERT_EQ(error, rv);
8652}
8653
8654TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8655 // Just check a grab bag of cert errors.
8656 static const int kErrors[] = {
8657 ERR_CERT_COMMON_NAME_INVALID,
8658 ERR_CERT_AUTHORITY_INVALID,
8659 ERR_CERT_DATE_INVALID,
8660 };
8661 for (size_t i = 0; i < arraysize(kErrors); i++) {
8662 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8663 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8664 }
8665}
8666
[email protected]bd0b6772011-01-11 19:59:308667// Ensure that a client certificate is removed from the SSL client auth
8668// cache when:
8669// 1) No proxy is involved.
8670// 2) TLS False Start is disabled.
8671// 3) The initial TLS handshake requests a client certificate.
8672// 4) The client supplies an invalid/unacceptable certificate.
8673TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278674 net::HttpRequestInfo request_info;
8675 request_info.url = GURL("https://www.example.com/");
8676 request_info.method = "GET";
8677 request_info.load_flags = net::LOAD_NORMAL;
8678
[email protected]bd0b6772011-01-11 19:59:308679 SessionDependencies session_deps;
8680
8681 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8682 cert_request->host_and_port = "www.example.com:443";
8683
8684 // [ssl_]data1 contains the data for the first SSL handshake. When a
8685 // CertificateRequest is received for the first time, the handshake will
8686 // be aborted to allow the caller to provide a certificate.
8687 SSLSocketDataProvider ssl_data1(true /* async */,
8688 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8689 ssl_data1.cert_request_info = cert_request.get();
8690 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8691 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8692 session_deps.socket_factory.AddSocketDataProvider(&data1);
8693
8694 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8695 // False Start is not being used, the result of the SSL handshake will be
8696 // returned as part of the SSLClientSocket::Connect() call. This test
8697 // matches the result of a server sending a handshake_failure alert,
8698 // rather than a Finished message, because it requires a client
8699 // certificate and none was supplied.
8700 SSLSocketDataProvider ssl_data2(true /* async */,
8701 net::ERR_SSL_PROTOCOL_ERROR);
8702 ssl_data2.cert_request_info = cert_request.get();
8703 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8704 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8705 session_deps.socket_factory.AddSocketDataProvider(&data2);
8706
8707 // [ssl_]data3 contains the data for the third SSL handshake. When a
8708 // connection to a server fails during an SSL handshake,
8709 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8710 // connection was attempted with TLSv1. This is transparent to the caller
8711 // of the HttpNetworkTransaction. Because this test failure is due to
8712 // requiring a client certificate, this fallback handshake should also
8713 // fail.
8714 SSLSocketDataProvider ssl_data3(true /* async */,
8715 net::ERR_SSL_PROTOCOL_ERROR);
8716 ssl_data3.cert_request_info = cert_request.get();
8717 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8718 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8719 session_deps.socket_factory.AddSocketDataProvider(&data3);
8720
8721 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8722 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8723
[email protected]bd0b6772011-01-11 19:59:308724 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]f1f3f0f82011-10-01 20:38:108725 TestOldCompletionCallback callback;
[email protected]bd0b6772011-01-11 19:59:308726 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8727 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8728
8729 // Complete the SSL handshake, which should abort due to requiring a
8730 // client certificate.
8731 rv = callback.WaitForResult();
8732 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8733
8734 // Indicate that no certificate should be supplied. From the perspective
8735 // of SSLClientCertCache, NULL is just as meaningful as a real
8736 // certificate, so this is the same as supply a
8737 // legitimate-but-unacceptable certificate.
8738 rv = trans->RestartWithCertificate(NULL, &callback);
8739 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8740
8741 // Ensure the certificate was added to the client auth cache before
8742 // allowing the connection to continue restarting.
8743 scoped_refptr<X509Certificate> client_cert;
8744 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8745 &client_cert));
8746 ASSERT_EQ(NULL, client_cert.get());
8747
8748 // Restart the handshake. This will consume ssl_data2, which fails, and
8749 // then consume ssl_data3, which should also fail. The result code is
8750 // checked against what ssl_data3 should return.
8751 rv = callback.WaitForResult();
8752 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8753
8754 // Ensure that the client certificate is removed from the cache on a
8755 // handshake failure.
8756 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8757 &client_cert));
8758}
8759
8760// Ensure that a client certificate is removed from the SSL client auth
8761// cache when:
8762// 1) No proxy is involved.
8763// 2) TLS False Start is enabled.
8764// 3) The initial TLS handshake requests a client certificate.
8765// 4) The client supplies an invalid/unacceptable certificate.
8766TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278767 net::HttpRequestInfo request_info;
8768 request_info.url = GURL("https://www.example.com/");
8769 request_info.method = "GET";
8770 request_info.load_flags = net::LOAD_NORMAL;
8771
[email protected]bd0b6772011-01-11 19:59:308772 SessionDependencies session_deps;
8773
8774 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8775 cert_request->host_and_port = "www.example.com:443";
8776
8777 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8778 // return successfully after reading up to the peer's Certificate message.
8779 // This is to allow the caller to call SSLClientSocket::Write(), which can
8780 // enqueue application data to be sent in the same packet as the
8781 // ChangeCipherSpec and Finished messages.
8782 // The actual handshake will be finished when SSLClientSocket::Read() is
8783 // called, which expects to process the peer's ChangeCipherSpec and
8784 // Finished messages. If there was an error negotiating with the peer,
8785 // such as due to the peer requiring a client certificate when none was
8786 // supplied, the alert sent by the peer won't be processed until Read() is
8787 // called.
8788
8789 // Like the non-False Start case, when a client certificate is requested by
8790 // the peer, the handshake is aborted during the Connect() call.
8791 // [ssl_]data1 represents the initial SSL handshake with the peer.
8792 SSLSocketDataProvider ssl_data1(true /* async */,
8793 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8794 ssl_data1.cert_request_info = cert_request.get();
8795 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8796 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8797 session_deps.socket_factory.AddSocketDataProvider(&data1);
8798
8799 // When a client certificate is supplied, Connect() will not be aborted
8800 // when the peer requests the certificate. Instead, the handshake will
8801 // artificially succeed, allowing the caller to write the HTTP request to
8802 // the socket. The handshake messages are not processed until Read() is
8803 // called, which then detects that the handshake was aborted, due to the
8804 // peer sending a handshake_failure because it requires a client
8805 // certificate.
8806 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8807 ssl_data2.cert_request_info = cert_request.get();
8808 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8809 net::MockRead data2_reads[] = {
8810 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8811 };
8812 net::StaticSocketDataProvider data2(
8813 data2_reads, arraysize(data2_reads), NULL, 0);
8814 session_deps.socket_factory.AddSocketDataProvider(&data2);
8815
8816 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8817 // the data for the SSL handshake once the TLSv1 connection falls back to
8818 // SSLv3. It has the same behaviour as [ssl_]data2.
8819 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8820 ssl_data3.cert_request_info = cert_request.get();
8821 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8822 net::StaticSocketDataProvider data3(
8823 data2_reads, arraysize(data2_reads), NULL, 0);
8824 session_deps.socket_factory.AddSocketDataProvider(&data3);
8825
8826 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8827 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8828
[email protected]bd0b6772011-01-11 19:59:308829 // Begin the initial SSL handshake.
[email protected]f1f3f0f82011-10-01 20:38:108830 TestOldCompletionCallback callback;
[email protected]bd0b6772011-01-11 19:59:308831 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8832 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8833
8834 // Complete the SSL handshake, which should abort due to requiring a
8835 // client certificate.
8836 rv = callback.WaitForResult();
8837 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8838
8839 // Indicate that no certificate should be supplied. From the perspective
8840 // of SSLClientCertCache, NULL is just as meaningful as a real
8841 // certificate, so this is the same as supply a
8842 // legitimate-but-unacceptable certificate.
8843 rv = trans->RestartWithCertificate(NULL, &callback);
8844 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8845
8846 // Ensure the certificate was added to the client auth cache before
8847 // allowing the connection to continue restarting.
8848 scoped_refptr<X509Certificate> client_cert;
8849 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8850 &client_cert));
8851 ASSERT_EQ(NULL, client_cert.get());
8852
8853
8854 // Restart the handshake. This will consume ssl_data2, which fails, and
8855 // then consume ssl_data3, which should also fail. The result code is
8856 // checked against what ssl_data3 should return.
8857 rv = callback.WaitForResult();
8858 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8859
8860 // Ensure that the client certificate is removed from the cache on a
8861 // handshake failure.
8862 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8863 &client_cert));
8864}
8865
[email protected]8c405132011-01-11 22:03:188866// Ensure that a client certificate is removed from the SSL client auth
8867// cache when:
8868// 1) An HTTPS proxy is involved.
8869// 3) The HTTPS proxy requests a client certificate.
8870// 4) The client supplies an invalid/unacceptable certificate for the
8871// proxy.
8872// The test is repeated twice, first for connecting to an HTTPS endpoint,
8873// then for connecting to an HTTP endpoint.
8874TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8875 SessionDependencies session_deps(
8876 ProxyService::CreateFixed("https://proxy:70"));
8877 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8878 session_deps.net_log = log.bound().net_log();
8879
8880 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8881 cert_request->host_and_port = "proxy:70";
8882
8883 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8884 // [ssl_]data[1-3]. Rather than represending the endpoint
8885 // (www.example.com:443), they represent failures with the HTTPS proxy
8886 // (proxy:70).
8887 SSLSocketDataProvider ssl_data1(true /* async */,
8888 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8889 ssl_data1.cert_request_info = cert_request.get();
8890 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8891 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8892 session_deps.socket_factory.AddSocketDataProvider(&data1);
8893
8894 SSLSocketDataProvider ssl_data2(true /* async */,
8895 net::ERR_SSL_PROTOCOL_ERROR);
8896 ssl_data2.cert_request_info = cert_request.get();
8897 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8898 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8899 session_deps.socket_factory.AddSocketDataProvider(&data2);
8900
8901 SSLSocketDataProvider ssl_data3(true /* async */,
8902 net::ERR_SSL_PROTOCOL_ERROR);
8903 ssl_data3.cert_request_info = cert_request.get();
8904 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8905 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8906 session_deps.socket_factory.AddSocketDataProvider(&data3);
8907
8908 net::HttpRequestInfo requests[2];
8909 requests[0].url = GURL("https://www.example.com/");
8910 requests[0].method = "GET";
8911 requests[0].load_flags = net::LOAD_NORMAL;
8912
8913 requests[1].url = GURL("http://www.example.com/");
8914 requests[1].method = "GET";
8915 requests[1].load_flags = net::LOAD_NORMAL;
8916
8917 for (size_t i = 0; i < arraysize(requests); ++i) {
8918 session_deps.socket_factory.ResetNextMockIndexes();
8919 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8920 scoped_ptr<HttpNetworkTransaction> trans(
8921 new HttpNetworkTransaction(session));
8922
8923 // Begin the SSL handshake with the proxy.
[email protected]f1f3f0f82011-10-01 20:38:108924 TestOldCompletionCallback callback;
[email protected]8c405132011-01-11 22:03:188925 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8926 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8927
8928 // Complete the SSL handshake, which should abort due to requiring a
8929 // client certificate.
8930 rv = callback.WaitForResult();
8931 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8932
8933 // Indicate that no certificate should be supplied. From the perspective
8934 // of SSLClientCertCache, NULL is just as meaningful as a real
8935 // certificate, so this is the same as supply a
8936 // legitimate-but-unacceptable certificate.
8937 rv = trans->RestartWithCertificate(NULL, &callback);
8938 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8939
8940 // Ensure the certificate was added to the client auth cache before
8941 // allowing the connection to continue restarting.
8942 scoped_refptr<X509Certificate> client_cert;
8943 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8944 &client_cert));
8945 ASSERT_EQ(NULL, client_cert.get());
8946 // Ensure the certificate was NOT cached for the endpoint. This only
8947 // applies to HTTPS requests, but is fine to check for HTTP requests.
8948 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8949 &client_cert));
8950
8951 // Restart the handshake. This will consume ssl_data2, which fails, and
8952 // then consume ssl_data3, which should also fail. The result code is
8953 // checked against what ssl_data3 should return.
8954 rv = callback.WaitForResult();
8955 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8956
8957 // Now that the new handshake has failed, ensure that the client
8958 // certificate was removed from the client auth cache.
8959 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8960 &client_cert));
8961 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8962 &client_cert));
8963 }
8964}
8965
[email protected]5c288bc2011-07-26 15:12:058966void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8967 SpdySessionPoolPeer* pool_peer,
8968 std::string host,
8969 int port,
8970 std::string iplist) {
8971 // Create a host resolver dependency that returns address |iplist| for
8972 // resolutions of |host|.
8973 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:048974
[email protected]5c288bc2011-07-26 15:12:058975 // Setup a HostPortProxyPair.
8976 HostPortPair host_port_pair(host, port);
8977 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
8978 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:048979
[email protected]5c288bc2011-07-26 15:12:058980 // Resolve the host and port.
8981 AddressList addresses;
8982 HostResolver::RequestInfo info(host_port_pair);
[email protected]f1f3f0f82011-10-01 20:38:108983 TestOldCompletionCallback callback;
[email protected]6e78dfb2011-07-28 21:34:478984 int rv = host_resolver->Resolve(info, &addresses, &callback, NULL,
8985 BoundNetLog());
8986 if (rv == ERR_IO_PENDING)
8987 rv = callback.WaitForResult();
8988 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:048989
[email protected]5c288bc2011-07-26 15:12:058990 // Add the first address as an alias. It would have been better to call
8991 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
8992 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
8993 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
8994 // the |pair|.
8995 const addrinfo* address = addresses.head();
8996 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:048997}
8998
[email protected]e3ceb682011-06-28 23:55:468999TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
9000 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349001 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469002
9003 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
9004 SessionDependencies session_deps;
9005 MockCachingHostResolver host_resolver;
9006 net::HttpNetworkSession::Params params;
9007 params.client_socket_factory = &session_deps.socket_factory;
9008 params.host_resolver = &host_resolver;
9009 params.cert_verifier = session_deps.cert_verifier.get();
9010 params.proxy_service = session_deps.proxy_service.get();
9011 params.ssl_config_service = session_deps.ssl_config_service;
9012 params.http_auth_handler_factory =
9013 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539014 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469015 params.net_log = session_deps.net_log;
9016 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269017 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9018 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469019
9020 SSLSocketDataProvider ssl(true, OK);
9021 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9022 ssl.next_proto = "spdy/2";
9023 ssl.was_npn_negotiated = true;
9024 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9025
9026 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9027 "https://www.google.com", false, 1, LOWEST));
9028 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9029 "https://www.gmail.com", false, 3, LOWEST));
9030 MockWrite spdy_writes[] = {
9031 CreateMockWrite(*host1_req, 1),
9032 CreateMockWrite(*host2_req, 4),
9033 };
9034 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9035 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9036 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9037 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9038 MockRead spdy_reads[] = {
9039 CreateMockRead(*host1_resp, 2),
9040 CreateMockRead(*host1_resp_body, 3),
9041 CreateMockRead(*host2_resp, 5),
9042 CreateMockRead(*host2_resp_body, 6),
9043 MockRead(true, 0, 7),
9044 };
9045
9046 scoped_refptr<OrderedSocketData> spdy_data(
9047 new OrderedSocketData(
9048 spdy_reads, arraysize(spdy_reads),
9049 spdy_writes, arraysize(spdy_writes)));
9050 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
9051
[email protected]f1f3f0f82011-10-01 20:38:109052 TestOldCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469053 HttpRequestInfo request1;
9054 request1.method = "GET";
9055 request1.url = GURL("https://www.google.com/");
9056 request1.load_flags = 0;
9057 HttpNetworkTransaction trans1(session);
9058
9059 int rv = trans1.Start(&request1, &callback, BoundNetLog());
9060 EXPECT_EQ(ERR_IO_PENDING, rv);
9061 EXPECT_EQ(OK, callback.WaitForResult());
9062
9063 const HttpResponseInfo* response = trans1.GetResponseInfo();
9064 ASSERT_TRUE(response != NULL);
9065 ASSERT_TRUE(response->headers != NULL);
9066 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9067
9068 std::string response_data;
9069 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9070 EXPECT_EQ("hello!", response_data);
9071
9072 // Preload www.gmail.com into HostCache.
9073 HostPortPair host_port("www.gmail.com", 443);
9074 HostResolver::RequestInfo resolve_info(host_port);
9075 AddressList ignored;
[email protected]6e78dfb2011-07-28 21:34:479076 rv = host_resolver.Resolve(resolve_info, &ignored, &callback, NULL,
9077 BoundNetLog());
9078 EXPECT_EQ(ERR_IO_PENDING, rv);
9079 rv = callback.WaitForResult();
9080 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469081
[email protected]5c288bc2011-07-26 15:12:059082 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9083 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9084 // (www.google.com, 443).
9085 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
9086 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049087
[email protected]e3ceb682011-06-28 23:55:469088 HttpRequestInfo request2;
9089 request2.method = "GET";
9090 request2.url = GURL("https://www.gmail.com/");
9091 request2.load_flags = 0;
9092 HttpNetworkTransaction trans2(session);
9093
9094 rv = trans2.Start(&request2, &callback, BoundNetLog());
9095 EXPECT_EQ(ERR_IO_PENDING, rv);
9096 EXPECT_EQ(OK, callback.WaitForResult());
9097
9098 response = trans2.GetResponseInfo();
9099 ASSERT_TRUE(response != NULL);
9100 ASSERT_TRUE(response->headers != NULL);
9101 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9102 EXPECT_TRUE(response->was_fetched_via_spdy);
9103 EXPECT_TRUE(response->was_npn_negotiated);
9104 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9105 EXPECT_EQ("hello!", response_data);
9106
[email protected]5285d972011-10-18 18:56:349107 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469108 HttpStreamFactory::set_use_alternate_protocols(false);
9109}
9110
9111class OneTimeCachingHostResolver : public net::HostResolver {
9112 public:
9113 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9114 : host_port_(host_port) {}
9115 virtual ~OneTimeCachingHostResolver() {}
9116
9117 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9118
9119 // HostResolver methods:
9120 virtual int Resolve(const RequestInfo& info,
9121 AddressList* addresses,
[email protected]f1f3f0f82011-10-01 20:38:109122 OldCompletionCallback* callback,
[email protected]e3ceb682011-06-28 23:55:469123 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:409124 const BoundNetLog& net_log) OVERRIDE {
9125 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:469126 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:409127 }
9128
9129 virtual int ResolveFromCache(const RequestInfo& info,
9130 AddressList* addresses,
9131 const BoundNetLog& net_log) OVERRIDE {
9132 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9133 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:099134 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:469135 return rv;
9136 }
9137
[email protected]95a214c2011-08-04 21:50:409138 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469139 host_resolver_.CancelRequest(req);
9140 }
9141
[email protected]95a214c2011-08-04 21:50:409142 virtual void AddObserver(Observer* observer) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469143 return host_resolver_.AddObserver(observer);
9144 }
9145
[email protected]3912662a32011-10-04 00:51:119146 virtual void RemoveObserver(Observer* observer) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469147 return host_resolver_.RemoveObserver(observer);
9148 }
9149
[email protected]46da33be2011-07-19 21:58:049150 MockCachingHostResolver* GetMockHostResolver() {
9151 return &host_resolver_;
9152 }
9153
[email protected]e3ceb682011-06-28 23:55:469154 private:
9155 MockCachingHostResolver host_resolver_;
9156 const HostPortPair host_port_;
9157};
9158
9159TEST_F(HttpNetworkTransactionTest,
9160 UseIPConnectionPoolingWithHostCacheExpiration) {
9161 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349162 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469163
9164 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9165 SessionDependencies session_deps;
9166 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9167 net::HttpNetworkSession::Params params;
9168 params.client_socket_factory = &session_deps.socket_factory;
9169 params.host_resolver = &host_resolver;
9170 params.cert_verifier = session_deps.cert_verifier.get();
9171 params.proxy_service = session_deps.proxy_service.get();
9172 params.ssl_config_service = session_deps.ssl_config_service;
9173 params.http_auth_handler_factory =
9174 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539175 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469176 params.net_log = session_deps.net_log;
9177 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269178 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9179 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469180
9181 SSLSocketDataProvider ssl(true, OK);
9182 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9183 ssl.next_proto = "spdy/2";
9184 ssl.was_npn_negotiated = true;
9185 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9186
9187 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9188 "https://www.google.com", false, 1, LOWEST));
9189 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9190 "https://www.gmail.com", false, 3, LOWEST));
9191 MockWrite spdy_writes[] = {
9192 CreateMockWrite(*host1_req, 1),
9193 CreateMockWrite(*host2_req, 4),
9194 };
9195 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9196 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9197 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9198 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9199 MockRead spdy_reads[] = {
9200 CreateMockRead(*host1_resp, 2),
9201 CreateMockRead(*host1_resp_body, 3),
9202 CreateMockRead(*host2_resp, 5),
9203 CreateMockRead(*host2_resp_body, 6),
9204 MockRead(true, 0, 7),
9205 };
9206
9207 scoped_refptr<OrderedSocketData> spdy_data(
9208 new OrderedSocketData(
9209 spdy_reads, arraysize(spdy_reads),
9210 spdy_writes, arraysize(spdy_writes)));
9211 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
9212
[email protected]f1f3f0f82011-10-01 20:38:109213 TestOldCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469214 HttpRequestInfo request1;
9215 request1.method = "GET";
9216 request1.url = GURL("https://www.google.com/");
9217 request1.load_flags = 0;
9218 HttpNetworkTransaction trans1(session);
9219
9220 int rv = trans1.Start(&request1, &callback, BoundNetLog());
9221 EXPECT_EQ(ERR_IO_PENDING, rv);
9222 EXPECT_EQ(OK, callback.WaitForResult());
9223
9224 const HttpResponseInfo* response = trans1.GetResponseInfo();
9225 ASSERT_TRUE(response != NULL);
9226 ASSERT_TRUE(response->headers != NULL);
9227 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9228
9229 std::string response_data;
9230 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9231 EXPECT_EQ("hello!", response_data);
9232
9233 // Preload cache entries into HostCache.
9234 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9235 AddressList ignored;
[email protected]6e78dfb2011-07-28 21:34:479236 rv = host_resolver.Resolve(resolve_info, &ignored, &callback, NULL,
9237 BoundNetLog());
9238 EXPECT_EQ(ERR_IO_PENDING, rv);
9239 rv = callback.WaitForResult();
9240 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469241
9242 HttpRequestInfo request2;
9243 request2.method = "GET";
9244 request2.url = GURL("https://www.gmail.com/");
9245 request2.load_flags = 0;
9246 HttpNetworkTransaction trans2(session);
9247
[email protected]5c288bc2011-07-26 15:12:059248 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9249 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9250 // (www.google.com, 443).
9251 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9252 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049253
[email protected]e3ceb682011-06-28 23:55:469254 rv = trans2.Start(&request2, &callback, BoundNetLog());
9255 EXPECT_EQ(ERR_IO_PENDING, rv);
9256 EXPECT_EQ(OK, callback.WaitForResult());
9257
9258 response = trans2.GetResponseInfo();
9259 ASSERT_TRUE(response != NULL);
9260 ASSERT_TRUE(response->headers != NULL);
9261 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9262 EXPECT_TRUE(response->was_fetched_via_spdy);
9263 EXPECT_TRUE(response->was_npn_negotiated);
9264 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9265 EXPECT_EQ("hello!", response_data);
9266
[email protected]5285d972011-10-18 18:56:349267 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469268 HttpStreamFactory::set_use_alternate_protocols(false);
9269}
9270
[email protected]5a60c8b2011-10-19 20:14:299271TEST_F(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
9272 MockRead data_reads1[] = {
9273 MockRead(false, ERR_PIPELINE_EVICTION),
9274 };
9275 MockRead data_reads2[] = {
9276 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9277 MockRead("hello world"),
9278 MockRead(false, OK),
9279 };
9280 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
9281 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
9282 StaticSocketDataProvider* data[] = { &data1, &data2 };
9283
9284 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9285
9286 EXPECT_EQ(OK, out.rv);
9287 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9288 EXPECT_EQ("hello world", out.response_data);
9289}
9290
9291TEST_F(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
9292 MockWrite data_writes1[] = {
9293 MockWrite(false, ERR_PIPELINE_EVICTION),
9294 };
9295 MockWrite data_writes2[] = {
9296 MockWrite("GET / HTTP/1.1\r\n"
9297 "Host: www.google.com\r\n"
9298 "Connection: keep-alive\r\n\r\n"),
9299 };
9300 MockRead data_reads2[] = {
9301 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9302 MockRead("hello world"),
9303 MockRead(false, OK),
9304 };
9305 StaticSocketDataProvider data1(NULL, 0,
9306 data_writes1, arraysize(data_writes1));
9307 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9308 data_writes2, arraysize(data_writes2));
9309 StaticSocketDataProvider* data[] = { &data1, &data2 };
9310
9311 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9312
9313 EXPECT_EQ(OK, out.rv);
9314 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9315 EXPECT_EQ("hello world", out.response_data);
9316}
9317
[email protected]89ceba9a2009-03-21 03:46:069318} // namespace net