blob: 3283345517dfc74792639463a2c78ef6ee29f27e [file] [log] [blame]
[email protected]eb6234e2012-01-19 01:50:021// Copyright (c) 2012 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"
[email protected]a42dbd142011-11-17 16:42:0248#include "net/socket/mock_client_socket_pool_manager.h"
[email protected]f7984fc62009-06-22 23:26:4449#include "net/socket/socket_test_util.h"
50#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5451#include "net/spdy/spdy_framer.h"
52#include "net/spdy/spdy_session.h"
53#include "net/spdy/spdy_session_pool.h"
54#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5255#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1556#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5257
58//-----------------------------------------------------------------------------
59
[email protected]13c8a092010-07-29 06:15:4460namespace {
61
62const string16 kBar(ASCIIToUTF16("bar"));
63const string16 kBar2(ASCIIToUTF16("bar2"));
64const string16 kBar3(ASCIIToUTF16("bar3"));
65const string16 kBaz(ASCIIToUTF16("baz"));
66const string16 kFirst(ASCIIToUTF16("first"));
67const string16 kFoo(ASCIIToUTF16("foo"));
68const string16 kFoo2(ASCIIToUTF16("foo2"));
69const string16 kFoo3(ASCIIToUTF16("foo3"));
70const string16 kFou(ASCIIToUTF16("fou"));
71const string16 kSecond(ASCIIToUTF16("second"));
72const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
73const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
74
[email protected]5285d972011-10-18 18:56:3475// MakeNextProtos is a utility function that returns a vector of std::strings
76// from its arguments. Don't forget to terminate the argument list with a NULL.
77std::vector<std::string> MakeNextProtos(const char* a, ...) {
78 std::vector<std::string> ret;
79 ret.push_back(a);
80
81 va_list args;
82 va_start(args, a);
83
84 for (;;) {
85 const char* value = va_arg(args, const char*);
86 if (value == NULL)
87 break;
88 ret.push_back(value);
89 }
90 va_end(args);
91
92 return ret;
93}
94
95// SpdyNextProtos returns a vector of NPN protocol strings for negotiating
96// SPDY.
97std::vector<std::string> SpdyNextProtos() {
[email protected]42baef7a2011-12-10 04:52:1098 return MakeNextProtos("http/1.1", "spdy/2", "spdy/2.1", NULL);
[email protected]5285d972011-10-18 18:56:3499}
100
[email protected]13c8a092010-07-29 06:15:44101} // namespace
102
[email protected]89ceba9a2009-03-21 03:46:06103namespace net {
104
[email protected]e44de5d2009-06-05 20:12:45105// Helper to manage the lifetimes of the dependencies for a
106// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44107struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59108 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42109 SessionDependencies()
110 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:15111 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:02112 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:10113 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08114 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:54115 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:54116 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59117
118 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45119 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42120 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:15121 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:42122 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10123 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08124 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:54125 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:54126 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59127
[email protected]73c45322010-10-01 23:57:54128 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:15129 scoped_ptr<CertVerifier> cert_verifier;
[email protected]6104ea5d2011-04-27 21:37:12130 scoped_ptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42131 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59132 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50133 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]17291a022011-10-10 07:32:53134 HttpServerPropertiesImpl http_server_properties;
[email protected]a7ea8832010-07-12 17:54:54135 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59136};
137
[email protected]228ff742009-06-05 01:19:59138HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]9e1bdd32011-02-03 21:48:34139 net::HttpNetworkSession::Params params;
140 params.client_socket_factory = &session_deps->socket_factory;
141 params.host_resolver = session_deps->host_resolver.get();
142 params.cert_verifier = session_deps->cert_verifier.get();
[email protected]6104ea5d2011-04-27 21:37:12143 params.proxy_service = session_deps->proxy_service.get();
[email protected]9e1bdd32011-02-03 21:48:34144 params.ssl_config_service = session_deps->ssl_config_service;
145 params.http_auth_handler_factory =
146 session_deps->http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:53147 params.http_server_properties = &session_deps->http_server_properties;
[email protected]9e1bdd32011-02-03 21:48:34148 params.net_log = session_deps->net_log;
149 return new HttpNetworkSession(params);
[email protected]e8d536192008-10-17 22:21:14150}
151
[email protected]89836e22008-09-25 20:33:42152class HttpNetworkTransactionTest : public PlatformTest {
[email protected]e3ceb682011-06-28 23:55:46153 protected:
154 struct SimpleGetHelperResult {
155 int rv;
156 std::string status_line;
157 std::string response_data;
158 };
159
[email protected]2ff8b312010-04-26 22:20:54160 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50161 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
162 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54163 spdy::SpdyFramer::set_enable_compression_default(false);
164 }
165
[email protected]0e75a732008-10-16 20:36:09166 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50167 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
168 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54169 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09170 // Empty the current queue.
171 MessageLoop::current()->RunAllPending();
172 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50173 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
174 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09175 }
176
[email protected]202965992011-12-07 23:04:51177 // Either |write_failure| specifies a write failure or |read_failure|
178 // specifies a read failure when using a reused socket. In either case, the
179 // failure should cause the network transaction to resend the request, and the
180 // other argument should be NULL.
181 void KeepAliveConnectionResendRequestTest(const MockWrite* write_failure,
182 const MockRead* read_failure);
initial.commit586acc5fe2008-07-26 22:42:52183
[email protected]5a60c8b2011-10-19 20:14:29184 SimpleGetHelperResult SimpleGetHelperForData(StaticSocketDataProvider* data[],
185 size_t data_count) {
[email protected]ff007e162009-05-23 09:13:15186 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52187
[email protected]ff007e162009-05-23 09:13:15188 HttpRequestInfo request;
189 request.method = "GET";
190 request.url = GURL("http://www.google.com/");
191 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52192
[email protected]cb9bf6ca2011-01-28 13:15:27193 SessionDependencies session_deps;
194 scoped_ptr<HttpTransaction> trans(
195 new HttpNetworkTransaction(CreateSession(&session_deps)));
196
[email protected]5a60c8b2011-10-19 20:14:29197 for (size_t i = 0; i < data_count; ++i) {
198 session_deps.socket_factory.AddSocketDataProvider(data[i]);
199 }
initial.commit586acc5fe2008-07-26 22:42:52200
[email protected]49639fa2011-12-20 23:22:41201 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52202
[email protected]169d0012010-05-10 23:20:12203 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40204 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]49639fa2011-12-20 23:22:41205 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]ff007e162009-05-23 09:13:15206 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52207
[email protected]ff007e162009-05-23 09:13:15208 out.rv = callback.WaitForResult();
209 if (out.rv != OK)
210 return out;
211
212 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50213 // Can't use ASSERT_* inside helper functions like this, so
214 // return an error.
215 if (response == NULL || response->headers == NULL) {
216 out.rv = ERR_UNEXPECTED;
217 return out;
218 }
[email protected]ff007e162009-05-23 09:13:15219 out.status_line = response->headers->GetStatusLine();
220
[email protected]6d81b482011-02-22 19:47:19221 EXPECT_EQ("192.0.2.33", response->socket_address.host());
222 EXPECT_EQ(0, response->socket_address.port());
223
[email protected]ff007e162009-05-23 09:13:15224 rv = ReadTransaction(trans.get(), &out.response_data);
225 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40226
227 net::CapturingNetLog::EntryList entries;
228 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39229 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40230 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12231 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39232 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40233 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39234 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
235 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15236
[email protected]b2fcd0e2010-12-01 15:19:40237 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40238 NetLogHttpRequestParameter* request_params =
239 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
240 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
241 EXPECT_EQ("Host: www.google.com\r\n"
242 "Connection: keep-alive\r\n\r\n",
243 request_params->GetHeaders().ToString());
244
[email protected]aecfbf22008-10-16 02:02:47245 return out;
[email protected]ff007e162009-05-23 09:13:15246 }
initial.commit586acc5fe2008-07-26 22:42:52247
[email protected]5a60c8b2011-10-19 20:14:29248 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
249 size_t reads_count) {
250 StaticSocketDataProvider reads(data_reads, reads_count, NULL, 0);
251 StaticSocketDataProvider* data[] = { &reads };
252 return SimpleGetHelperForData(data, 1);
253 }
254
[email protected]ff007e162009-05-23 09:13:15255 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
256 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52257
[email protected]ff007e162009-05-23 09:13:15258 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15259};
[email protected]231d5a32008-09-13 00:45:27260
[email protected]15a5ccf82008-10-23 19:57:43261// Fill |str| with a long header list that consumes >= |size| bytes.
262void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19263 const char* row =
264 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
265 const int sizeof_row = strlen(row);
266 const int num_rows = static_cast<int>(
267 ceil(static_cast<float>(size) / sizeof_row));
268 const int sizeof_data = num_rows * sizeof_row;
269 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43270 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51271
[email protected]4ddaf2502008-10-23 18:26:19272 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43273 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19274}
275
[email protected]385a4672009-03-11 22:21:29276// Alternative functions that eliminate randomness and dependency on the local
277// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20278void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29279 static const uint8 bytes[] = {
280 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
281 };
282 static size_t current_byte = 0;
283 for (size_t i = 0; i < n; ++i) {
284 output[i] = bytes[current_byte++];
285 current_byte %= arraysize(bytes);
286 }
287}
288
[email protected]fe2bc6a2009-03-23 16:52:20289void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29290 static const uint8 bytes[] = {
291 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
292 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
293 };
294 static size_t current_byte = 0;
295 for (size_t i = 0; i < n; ++i) {
296 output[i] = bytes[current_byte++];
297 current_byte %= arraysize(bytes);
298 }
299}
300
[email protected]fe2bc6a2009-03-23 16:52:20301std::string MockGetHostName() {
302 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29303}
304
[email protected]e60e47a2010-07-14 03:37:18305template<typename ParentPool>
306class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31307 public:
[email protected]9e1bdd32011-02-03 21:48:34308 CaptureGroupNameSocketPool(HostResolver* host_resolver,
309 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18310
[email protected]d80a4322009-08-14 07:07:49311 const std::string last_group_name_received() const {
312 return last_group_name_;
313 }
314
[email protected]684970b2009-08-14 04:54:46315 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49316 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31317 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31318 ClientSocketHandle* handle,
[email protected]49639fa2011-12-20 23:22:41319 const CompletionCallback& callback,
[email protected]9e743cd2010-03-16 07:03:53320 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31321 last_group_name_ = group_name;
322 return ERR_IO_PENDING;
323 }
[email protected]04e5be32009-06-26 20:00:31324 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21325 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31326 virtual void ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10327 StreamSocket* socket,
[email protected]9f95c692011-02-11 19:20:19328 int id) {}
[email protected]04e5be32009-06-26 20:00:31329 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31330 virtual int IdleSocketCount() const {
331 return 0;
332 }
333 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
334 return 0;
335 }
336 virtual LoadState GetLoadState(const std::string& group_name,
337 const ClientSocketHandle* handle) const {
338 return LOAD_STATE_IDLE;
339 }
[email protected]a796bcec2010-03-22 17:17:26340 virtual base::TimeDelta ConnectionTimeout() const {
341 return base::TimeDelta();
342 }
[email protected]d80a4322009-08-14 07:07:49343
344 private:
[email protected]04e5be32009-06-26 20:00:31345 std::string last_group_name_;
346};
347
[email protected]ab739042011-04-07 15:22:28348typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
349CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13350typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
351CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06352typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11353CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18354typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
355CaptureGroupNameSSLSocketPool;
356
357template<typename ParentPool>
358CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34359 HostResolver* host_resolver,
360 CertVerifier* /* cert_verifier */)
361 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18362
363template<>
[email protected]2df19bb2010-08-25 20:13:46364CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34365 HostResolver* host_resolver,
366 CertVerifier* /* cert_verifier */)
367 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
[email protected]2df19bb2010-08-25 20:13:46368
369template<>
[email protected]e60e47a2010-07-14 03:37:18370CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34371 HostResolver* host_resolver,
372 CertVerifier* cert_verifier)
[email protected]3ed7496f2011-12-15 18:27:40373 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL,
[email protected]c3456bb2011-12-12 22:22:19374 NULL, NULL, "", NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11375
[email protected]231d5a32008-09-13 00:45:27376//-----------------------------------------------------------------------------
377
[email protected]dae22c52010-07-30 02:16:35378// This is the expected return from a current server advertising SPDY.
379static const char kAlternateProtocolHttpHeader[] =
[email protected]8d2f7012012-02-16 00:08:04380 "Alternate-Protocol: 443:npn-spdy/2.1\r\n\r\n";
[email protected]dae22c52010-07-30 02:16:35381
[email protected]79cb5c12011-09-12 13:12:04382// Helper functions for validating that AuthChallengeInfo's are correctly
383// configured for common cases.
384bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
385 if (!auth_challenge)
386 return false;
387 EXPECT_FALSE(auth_challenge->is_proxy);
388 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
389 EXPECT_EQ("MyRealm1", auth_challenge->realm);
390 EXPECT_EQ("basic", auth_challenge->scheme);
391 return true;
392}
393
394bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
395 if (!auth_challenge)
396 return false;
397 EXPECT_TRUE(auth_challenge->is_proxy);
398 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
399 EXPECT_EQ("MyRealm1", auth_challenge->realm);
400 EXPECT_EQ("basic", auth_challenge->scheme);
401 return true;
402}
403
404bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
405 if (!auth_challenge)
406 return false;
407 EXPECT_FALSE(auth_challenge->is_proxy);
408 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
409 EXPECT_EQ("digestive", auth_challenge->realm);
410 EXPECT_EQ("digest", auth_challenge->scheme);
411 return true;
412}
413
414bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
415 if (!auth_challenge)
416 return false;
417 EXPECT_FALSE(auth_challenge->is_proxy);
418 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
419 EXPECT_EQ(std::string(), auth_challenge->realm);
420 EXPECT_EQ("ntlm", auth_challenge->scheme);
421 return true;
422}
423
[email protected]231d5a32008-09-13 00:45:27424TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59425 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40426 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43427 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27428}
429
430TEST_F(HttpNetworkTransactionTest, SimpleGET) {
431 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35432 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
433 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42434 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27435 };
[email protected]31a2bfe2010-02-09 08:03:39436 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
437 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42438 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27439 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
440 EXPECT_EQ("hello world", out.response_data);
441}
442
443// Response with no status line.
444TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
445 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35446 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42447 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27448 };
[email protected]31a2bfe2010-02-09 08:03:39449 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
450 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42451 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27452 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
453 EXPECT_EQ("hello world", out.response_data);
454}
455
456// Allow up to 4 bytes of junk to precede status line.
457TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
458 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35459 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42460 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27461 };
[email protected]31a2bfe2010-02-09 08:03:39462 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
463 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42464 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27465 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
466 EXPECT_EQ("DATA", out.response_data);
467}
468
469// Allow up to 4 bytes of junk to precede status line.
470TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
471 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35472 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42473 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27474 };
[email protected]31a2bfe2010-02-09 08:03:39475 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
476 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42477 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27478 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
479 EXPECT_EQ("DATA", out.response_data);
480}
481
482// Beyond 4 bytes of slop and it should fail to find a status line.
483TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
484 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35485 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42486 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27487 };
[email protected]31a2bfe2010-02-09 08:03:39488 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
489 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42490 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25491 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
492 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27493}
494
495// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
496TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
497 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35498 MockRead("\n"),
499 MockRead("\n"),
500 MockRead("Q"),
501 MockRead("J"),
502 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42503 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27504 };
[email protected]31a2bfe2010-02-09 08:03:39505 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
506 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42507 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27508 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
509 EXPECT_EQ("DATA", out.response_data);
510}
511
512// Close the connection before enough bytes to have a status line.
513TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
514 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35515 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42516 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27517 };
[email protected]31a2bfe2010-02-09 08:03:39518 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
519 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42520 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27521 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
522 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52523}
524
[email protected]f9d44aa2008-09-23 23:57:17525// Simulate a 204 response, lacking a Content-Length header, sent over a
526// persistent connection. The response should still terminate since a 204
527// cannot have a response body.
528TEST_F(HttpNetworkTransactionTest, StopsReading204) {
529 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35530 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
531 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42532 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17533 };
[email protected]31a2bfe2010-02-09 08:03:39534 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
535 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42536 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17537 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
538 EXPECT_EQ("", out.response_data);
539}
540
[email protected]0877e3d2009-10-17 22:29:57541// A simple request using chunked encoding with some extra data after.
542// (Like might be seen in a pipelined response.)
543TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
544 MockRead data_reads[] = {
545 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
546 MockRead("5\r\nHello\r\n"),
547 MockRead("1\r\n"),
548 MockRead(" \r\n"),
549 MockRead("5\r\nworld\r\n"),
550 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
551 MockRead(false, OK),
552 };
[email protected]31a2bfe2010-02-09 08:03:39553 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
554 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57555 EXPECT_EQ(OK, out.rv);
556 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
557 EXPECT_EQ("Hello world", out.response_data);
558}
559
[email protected]9fe44f52010-09-23 18:36:00560// Next tests deal with http://crbug.com/56344.
561
562TEST_F(HttpNetworkTransactionTest,
563 MultipleContentLengthHeadersNoTransferEncoding) {
564 MockRead data_reads[] = {
565 MockRead("HTTP/1.1 200 OK\r\n"),
566 MockRead("Content-Length: 10\r\n"),
567 MockRead("Content-Length: 5\r\n\r\n"),
568 };
569 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
570 arraysize(data_reads));
571 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
572}
573
574TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04575 DuplicateContentLengthHeadersNoTransferEncoding) {
576 MockRead data_reads[] = {
577 MockRead("HTTP/1.1 200 OK\r\n"),
578 MockRead("Content-Length: 5\r\n"),
579 MockRead("Content-Length: 5\r\n\r\n"),
580 MockRead("Hello"),
581 };
582 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
583 arraysize(data_reads));
584 EXPECT_EQ(OK, out.rv);
585 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
586 EXPECT_EQ("Hello", out.response_data);
587}
588
589TEST_F(HttpNetworkTransactionTest,
590 ComplexContentLengthHeadersNoTransferEncoding) {
591 // More than 2 dupes.
592 {
593 MockRead data_reads[] = {
594 MockRead("HTTP/1.1 200 OK\r\n"),
595 MockRead("Content-Length: 5\r\n"),
596 MockRead("Content-Length: 5\r\n"),
597 MockRead("Content-Length: 5\r\n\r\n"),
598 MockRead("Hello"),
599 };
600 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
601 arraysize(data_reads));
602 EXPECT_EQ(OK, out.rv);
603 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
604 EXPECT_EQ("Hello", out.response_data);
605 }
606 // HTTP/1.0
607 {
608 MockRead data_reads[] = {
609 MockRead("HTTP/1.0 200 OK\r\n"),
610 MockRead("Content-Length: 5\r\n"),
611 MockRead("Content-Length: 5\r\n"),
612 MockRead("Content-Length: 5\r\n\r\n"),
613 MockRead("Hello"),
614 };
615 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
616 arraysize(data_reads));
617 EXPECT_EQ(OK, out.rv);
618 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
619 EXPECT_EQ("Hello", out.response_data);
620 }
621 // 2 dupes and one mismatched.
622 {
623 MockRead data_reads[] = {
624 MockRead("HTTP/1.1 200 OK\r\n"),
625 MockRead("Content-Length: 10\r\n"),
626 MockRead("Content-Length: 10\r\n"),
627 MockRead("Content-Length: 5\r\n\r\n"),
628 };
629 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
630 arraysize(data_reads));
631 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
632 }
633}
634
635TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00636 MultipleContentLengthHeadersTransferEncoding) {
637 MockRead data_reads[] = {
638 MockRead("HTTP/1.1 200 OK\r\n"),
639 MockRead("Content-Length: 666\r\n"),
640 MockRead("Content-Length: 1337\r\n"),
641 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
642 MockRead("5\r\nHello\r\n"),
643 MockRead("1\r\n"),
644 MockRead(" \r\n"),
645 MockRead("5\r\nworld\r\n"),
646 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
647 MockRead(false, OK),
648 };
649 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
650 arraysize(data_reads));
651 EXPECT_EQ(OK, out.rv);
652 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
653 EXPECT_EQ("Hello world", out.response_data);
654}
655
[email protected]1628fe92011-10-04 23:04:55656// Next tests deal with http://crbug.com/98895.
657
658// Checks that a single Content-Disposition header results in no error.
659TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
660 MockRead data_reads[] = {
661 MockRead("HTTP/1.1 200 OK\r\n"),
662 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
663 MockRead("Content-Length: 5\r\n\r\n"),
664 MockRead("Hello"),
665 };
666 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
667 arraysize(data_reads));
668 EXPECT_EQ(OK, out.rv);
669 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
670 EXPECT_EQ("Hello", out.response_data);
671}
672
673// Checks that two identical Content-Disposition headers result in an error.
674TEST_F(HttpNetworkTransactionTest,
675 DuplicateIdenticalContentDispositionHeaders) {
676 MockRead data_reads[] = {
677 MockRead("HTTP/1.1 200 OK\r\n"),
678 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
679 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
680 MockRead("Content-Length: 5\r\n\r\n"),
681 MockRead("Hello"),
682 };
683 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
684 arraysize(data_reads));
685 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
686}
687
688// Checks that two distinct Content-Disposition headers result in an error.
689TEST_F(HttpNetworkTransactionTest, DuplicateDistinctContentDispositionHeaders) {
690 MockRead data_reads[] = {
691 MockRead("HTTP/1.1 200 OK\r\n"),
692 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
693 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
694 MockRead("Content-Length: 5\r\n\r\n"),
695 MockRead("Hello"),
696 };
697 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
698 arraysize(data_reads));
699 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
700}
701
702// Checks the behavior of a single Location header.
703TEST_F(HttpNetworkTransactionTest, SingleLocationHeader) {
704 MockRead data_reads[] = {
705 MockRead("HTTP/1.1 302 Redirect\r\n"),
706 MockRead("Location: http://good.com/\r\n"),
707 MockRead("Content-Length: 0\r\n\r\n"),
708 MockRead(false, OK),
709 };
710
711 HttpRequestInfo request;
712 request.method = "GET";
713 request.url = GURL("http://redirect.com/");
714 request.load_flags = 0;
715
716 SessionDependencies session_deps;
717 scoped_ptr<HttpTransaction> trans(
718 new HttpNetworkTransaction(CreateSession(&session_deps)));
719
720 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
721 session_deps.socket_factory.AddSocketDataProvider(&data);
722
[email protected]49639fa2011-12-20 23:22:41723 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:55724
[email protected]49639fa2011-12-20 23:22:41725 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1628fe92011-10-04 23:04:55726 EXPECT_EQ(ERR_IO_PENDING, rv);
727
728 EXPECT_EQ(OK, callback.WaitForResult());
729
730 const HttpResponseInfo* response = trans->GetResponseInfo();
731 ASSERT_TRUE(response != NULL && response->headers != NULL);
732 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
733 std::string url;
734 EXPECT_TRUE(response->headers->IsRedirect(&url));
735 EXPECT_EQ("http://good.com/", url);
736}
737
738// Checks that two identical Location headers result in an error.
739TEST_F(HttpNetworkTransactionTest, DuplicateIdenticalLocationHeaders) {
740 MockRead data_reads[] = {
741 MockRead("HTTP/1.1 302 Redirect\r\n"),
742 MockRead("Location: http://good.com/\r\n"),
743 MockRead("Location: http://good.com/\r\n"),
744 MockRead("Content-Length: 0\r\n\r\n"),
745 MockRead(false, OK),
746 };
747 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
748 arraysize(data_reads));
749 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
750}
751
752// Checks that two distinct Location headers result in an error.
753TEST_F(HttpNetworkTransactionTest, DuplicateDistinctLocationHeaders) {
754 MockRead data_reads[] = {
755 MockRead("HTTP/1.1 302 Redirect\r\n"),
756 MockRead("Location: http://good.com/\r\n"),
757 MockRead("Location: http://evil.com/\r\n"),
758 MockRead("Content-Length: 0\r\n\r\n"),
759 MockRead(false, OK),
760 };
761 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
762 arraysize(data_reads));
763 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
764}
765
[email protected]ef0faf2e72009-03-05 23:27:23766// Do a request using the HEAD method. Verify that we don't try to read the
767// message body (since HEAD has none).
768TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42769 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23770 request.method = "HEAD";
771 request.url = GURL("http://www.google.com/");
772 request.load_flags = 0;
773
[email protected]cb9bf6ca2011-01-28 13:15:27774 SessionDependencies session_deps;
775 scoped_ptr<HttpTransaction> trans(
776 new HttpNetworkTransaction(CreateSession(&session_deps)));
777
[email protected]ef0faf2e72009-03-05 23:27:23778 MockWrite data_writes1[] = {
779 MockWrite("HEAD / HTTP/1.1\r\n"
780 "Host: www.google.com\r\n"
781 "Connection: keep-alive\r\n"
782 "Content-Length: 0\r\n\r\n"),
783 };
784 MockRead data_reads1[] = {
785 MockRead("HTTP/1.1 404 Not Found\r\n"),
786 MockRead("Server: Blah\r\n"),
787 MockRead("Content-Length: 1234\r\n\r\n"),
788
789 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42790 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23791 };
792
[email protected]31a2bfe2010-02-09 08:03:39793 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
794 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59795 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23796
[email protected]49639fa2011-12-20 23:22:41797 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:23798
[email protected]49639fa2011-12-20 23:22:41799 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23801
802 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42803 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23804
[email protected]1c773ea12009-04-28 19:58:42805 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50806 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:23807
808 // Check that the headers got parsed.
809 EXPECT_TRUE(response->headers != NULL);
810 EXPECT_EQ(1234, response->headers->GetContentLength());
811 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
812
813 std::string server_header;
814 void* iter = NULL;
815 bool has_server_header = response->headers->EnumerateHeader(
816 &iter, "Server", &server_header);
817 EXPECT_TRUE(has_server_header);
818 EXPECT_EQ("Blah", server_header);
819
820 // Reading should give EOF right away, since there is no message body
821 // (despite non-zero content-length).
822 std::string response_data;
823 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42824 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23825 EXPECT_EQ("", response_data);
826}
827
initial.commit586acc5fe2008-07-26 22:42:52828TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59829 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27830 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52831
832 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35833 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
834 MockRead("hello"),
835 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
836 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42837 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52838 };
[email protected]31a2bfe2010-02-09 08:03:39839 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59840 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52841
[email protected]0b0bf032010-09-21 18:08:50842 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52843 "hello", "world"
844 };
845
846 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42847 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52848 request.method = "GET";
849 request.url = GURL("http://www.google.com/");
850 request.load_flags = 0;
851
[email protected]cb9bf6ca2011-01-28 13:15:27852 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
853
[email protected]49639fa2011-12-20 23:22:41854 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52855
[email protected]49639fa2011-12-20 23:22:41856 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42857 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52858
859 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42860 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52861
[email protected]1c773ea12009-04-28 19:58:42862 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50863 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52864
865 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25866 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52867
868 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57869 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42870 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25871 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52872 }
873}
874
875TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42876 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52877 request.method = "POST";
878 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42879 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52880 request.upload_data->AppendBytes("foo", 3);
881 request.load_flags = 0;
882
[email protected]cb9bf6ca2011-01-28 13:15:27883 SessionDependencies session_deps;
884 scoped_ptr<HttpTransaction> trans(
885 new HttpNetworkTransaction(CreateSession(&session_deps)));
886
initial.commit586acc5fe2008-07-26 22:42:52887 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35888 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
889 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
890 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42891 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52892 };
[email protected]31a2bfe2010-02-09 08:03:39893 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59894 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52895
[email protected]49639fa2011-12-20 23:22:41896 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52897
[email protected]49639fa2011-12-20 23:22:41898 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42899 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52900
901 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42902 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52903
[email protected]1c773ea12009-04-28 19:58:42904 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50905 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52906
907 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25908 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52909
910 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57911 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42912 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25913 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52914}
915
[email protected]3a2d3662009-03-27 03:49:14916// This test is almost the same as Ignores100 above, but the response contains
917// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57918// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14919TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42920 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14921 request.method = "GET";
922 request.url = GURL("http://www.foo.com/");
923 request.load_flags = 0;
924
[email protected]cb9bf6ca2011-01-28 13:15:27925 SessionDependencies session_deps;
926 scoped_ptr<HttpTransaction> trans(
927 new HttpNetworkTransaction(CreateSession(&session_deps)));
928
[email protected]3a2d3662009-03-27 03:49:14929 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57930 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
931 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14932 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42933 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14934 };
[email protected]31a2bfe2010-02-09 08:03:39935 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59936 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14937
[email protected]49639fa2011-12-20 23:22:41938 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:14939
[email protected]49639fa2011-12-20 23:22:41940 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42941 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14942
943 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42944 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14945
[email protected]1c773ea12009-04-28 19:58:42946 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50947 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:14948
949 EXPECT_TRUE(response->headers != NULL);
950 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
951
952 std::string response_data;
953 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42954 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14955 EXPECT_EQ("hello world", response_data);
956}
957
[email protected]ee9410e72010-01-07 01:42:38958TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38959 HttpRequestInfo request;
960 request.method = "POST";
961 request.url = GURL("http://www.foo.com/");
962 request.load_flags = 0;
963
[email protected]cb9bf6ca2011-01-28 13:15:27964 SessionDependencies session_deps;
965 scoped_ptr<HttpTransaction> trans(
966 new HttpNetworkTransaction(CreateSession(&session_deps)));
967
[email protected]ee9410e72010-01-07 01:42:38968 MockRead data_reads[] = {
969 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
970 MockRead(true, 0),
971 };
[email protected]31a2bfe2010-02-09 08:03:39972 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38973 session_deps.socket_factory.AddSocketDataProvider(&data);
974
[email protected]49639fa2011-12-20 23:22:41975 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:38976
[email protected]49639fa2011-12-20 23:22:41977 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38978 EXPECT_EQ(ERR_IO_PENDING, rv);
979
980 rv = callback.WaitForResult();
981 EXPECT_EQ(OK, rv);
982
983 std::string response_data;
984 rv = ReadTransaction(trans.get(), &response_data);
985 EXPECT_EQ(OK, rv);
986 EXPECT_EQ("", response_data);
987}
988
989TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38990 HttpRequestInfo request;
991 request.method = "POST";
992 request.url = GURL("http://www.foo.com/");
993 request.load_flags = 0;
994
[email protected]cb9bf6ca2011-01-28 13:15:27995 SessionDependencies session_deps;
996 scoped_ptr<HttpTransaction> trans(
997 new HttpNetworkTransaction(CreateSession(&session_deps)));
998
[email protected]ee9410e72010-01-07 01:42:38999 MockRead data_reads[] = {
1000 MockRead(true, 0),
1001 };
[email protected]31a2bfe2010-02-09 08:03:391002 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:381003 session_deps.socket_factory.AddSocketDataProvider(&data);
1004
[email protected]49639fa2011-12-20 23:22:411005 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381006
[email protected]49639fa2011-12-20 23:22:411007 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381008 EXPECT_EQ(ERR_IO_PENDING, rv);
1009
1010 rv = callback.WaitForResult();
1011 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1012}
1013
[email protected]3d2a59b2008-09-26 19:44:251014void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511015 const MockWrite* write_failure,
1016 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421017 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521018 request.method = "GET";
1019 request.url = GURL("http://www.foo.com/");
1020 request.load_flags = 0;
1021
[email protected]cb9bf6ca2011-01-28 13:15:271022 SessionDependencies session_deps;
1023 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1024
[email protected]202965992011-12-07 23:04:511025 // Written data for successfully sending both requests.
1026 MockWrite data1_writes[] = {
1027 MockWrite("GET / HTTP/1.1\r\n"
1028 "Host: www.foo.com\r\n"
1029 "Connection: keep-alive\r\n\r\n"),
1030 MockWrite("GET / HTTP/1.1\r\n"
1031 "Host: www.foo.com\r\n"
1032 "Connection: keep-alive\r\n\r\n")
1033 };
1034
1035 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521036 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351037 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1038 MockRead("hello"),
[email protected]202965992011-12-07 23:04:511039 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:521040 };
[email protected]202965992011-12-07 23:04:511041
1042 if (write_failure) {
1043 ASSERT_TRUE(!read_failure);
1044 data1_writes[1] = *write_failure;
1045 } else {
1046 ASSERT_TRUE(read_failure);
1047 data1_reads[2] = *read_failure;
1048 }
1049
1050 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1051 data1_writes, arraysize(data1_writes));
[email protected]5ecc992a42009-11-11 01:41:591052 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521053
1054 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351055 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1056 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:421057 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:521058 };
[email protected]31a2bfe2010-02-09 08:03:391059 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591060 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521061
1062 const char* kExpectedResponseData[] = {
1063 "hello", "world"
1064 };
1065
1066 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411067 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521068
[email protected]5695b8c2009-09-30 21:36:431069 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:521070
[email protected]49639fa2011-12-20 23:22:411071 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421072 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521073
1074 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421075 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521076
[email protected]1c773ea12009-04-28 19:58:421077 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501078 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521079
1080 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:251081 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521082
1083 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571084 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421085 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251086 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521087 }
1088}
[email protected]3d2a59b2008-09-26 19:44:251089
[email protected]202965992011-12-07 23:04:511090TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
1091 MockWrite write_failure(true, ERR_SOCKET_NOT_CONNECTED);
1092 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1093}
1094
[email protected]3d2a59b2008-09-26 19:44:251095TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421096 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511097 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251098}
1099
1100TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:421101 MockRead read_failure(false, OK); // EOF
[email protected]202965992011-12-07 23:04:511102 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251103}
1104
1105TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421106 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251107 request.method = "GET";
1108 request.url = GURL("http://www.google.com/");
1109 request.load_flags = 0;
1110
[email protected]cb9bf6ca2011-01-28 13:15:271111 SessionDependencies session_deps;
1112 scoped_ptr<HttpTransaction> trans(
1113 new HttpNetworkTransaction(CreateSession(&session_deps)));
1114
[email protected]3d2a59b2008-09-26 19:44:251115 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421116 MockRead(true, ERR_CONNECTION_RESET),
[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 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591122 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251123
[email protected]49639fa2011-12-20 23:22:411124 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251125
[email protected]49639fa2011-12-20 23:22:411126 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421127 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251128
1129 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421130 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:251131
[email protected]1c773ea12009-04-28 19:58:421132 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:251133 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:251134}
1135
1136// What do various browsers do when the server closes a non-keepalive
1137// connection without sending any response header or body?
1138//
1139// IE7: error page
1140// Safari 3.1.2 (Windows): error page
1141// Firefox 3.0.1: blank page
1142// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421143// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1144// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:251145TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1146 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421147 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:351148 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1149 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:421150 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:251151 };
[email protected]31a2bfe2010-02-09 08:03:391152 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1153 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421154 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251155}
[email protected]038e9a32008-10-08 22:40:161156
[email protected]0b0bf032010-09-21 18:08:501157// Test that we correctly reuse a keep-alive connection after not explicitly
1158// reading the body.
1159TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131160 HttpRequestInfo request;
1161 request.method = "GET";
1162 request.url = GURL("http://www.foo.com/");
1163 request.load_flags = 0;
1164
[email protected]cb9bf6ca2011-01-28 13:15:271165 SessionDependencies session_deps;
1166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1167
[email protected]0b0bf032010-09-21 18:08:501168 // Note that because all these reads happen in the same
1169 // StaticSocketDataProvider, it shows that the same socket is being reused for
1170 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:131171 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:501172 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1173 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:131174 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:501175 MockRead("HTTP/1.1 302 Found\r\n"
1176 "Content-Length: 0\r\n\r\n"),
1177 MockRead("HTTP/1.1 302 Found\r\n"
1178 "Content-Length: 5\r\n\r\n"
1179 "hello"),
1180 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1181 "Content-Length: 0\r\n\r\n"),
1182 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1183 "Content-Length: 5\r\n\r\n"
1184 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131185 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1186 MockRead("hello"),
1187 };
1188 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1189 session_deps.socket_factory.AddSocketDataProvider(&data1);
1190
1191 MockRead data2_reads[] = {
1192 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
1193 };
1194 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1195 session_deps.socket_factory.AddSocketDataProvider(&data2);
1196
[email protected]0b0bf032010-09-21 18:08:501197 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1198 std::string response_lines[kNumUnreadBodies];
1199
1200 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411201 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131202
1203 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1204
[email protected]49639fa2011-12-20 23:22:411205 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]fc31d6a42010-06-24 18:05:131206 EXPECT_EQ(ERR_IO_PENDING, rv);
1207
1208 rv = callback.WaitForResult();
1209 EXPECT_EQ(OK, rv);
1210
1211 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501212 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131213
[email protected]0b0bf032010-09-21 18:08:501214 ASSERT_TRUE(response->headers != NULL);
1215 response_lines[i] = response->headers->GetStatusLine();
1216
1217 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131218 }
[email protected]0b0bf032010-09-21 18:08:501219
1220 const char* const kStatusLines[] = {
1221 "HTTP/1.1 204 No Content",
1222 "HTTP/1.1 205 Reset Content",
1223 "HTTP/1.1 304 Not Modified",
1224 "HTTP/1.1 302 Found",
1225 "HTTP/1.1 302 Found",
1226 "HTTP/1.1 301 Moved Permanently",
1227 "HTTP/1.1 301 Moved Permanently",
1228 };
1229
1230 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1231 forgot_to_update_kStatusLines);
1232
1233 for (int i = 0; i < kNumUnreadBodies; ++i)
1234 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1235
[email protected]49639fa2011-12-20 23:22:411236 TestCompletionCallback callback;
[email protected]0b0bf032010-09-21 18:08:501237 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411238 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0b0bf032010-09-21 18:08:501239 EXPECT_EQ(ERR_IO_PENDING, rv);
1240 rv = callback.WaitForResult();
1241 EXPECT_EQ(OK, rv);
1242 const HttpResponseInfo* response = trans->GetResponseInfo();
1243 ASSERT_TRUE(response != NULL);
1244 ASSERT_TRUE(response->headers != NULL);
1245 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1246 std::string response_data;
1247 rv = ReadTransaction(trans.get(), &response_data);
1248 EXPECT_EQ(OK, rv);
1249 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131250}
1251
[email protected]038e9a32008-10-08 22:40:161252// Test the request-challenge-retry sequence for basic auth.
1253// (basic auth is the easiest to mock, because it has no randomness).
1254TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421255 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161256 request.method = "GET";
1257 request.url = GURL("http://www.google.com/");
1258 request.load_flags = 0;
1259
[email protected]cb9bf6ca2011-01-28 13:15:271260 SessionDependencies session_deps;
1261 scoped_ptr<HttpTransaction> trans(
1262 new HttpNetworkTransaction(CreateSession(&session_deps)));
1263
[email protected]f9ee6b52008-11-08 06:46:231264 MockWrite data_writes1[] = {
1265 MockWrite("GET / HTTP/1.1\r\n"
1266 "Host: www.google.com\r\n"
1267 "Connection: keep-alive\r\n\r\n"),
1268 };
1269
[email protected]038e9a32008-10-08 22:40:161270 MockRead data_reads1[] = {
1271 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1272 // Give a couple authenticate options (only the middle one is actually
1273 // supported).
[email protected]22927ad2009-09-21 19:56:191274 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161275 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1276 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1277 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1278 // Large content-length -- won't matter, as connection will be reset.
1279 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421280 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161281 };
1282
1283 // After calling trans->RestartWithAuth(), this is the request we should
1284 // be issuing -- the final header line contains the credentials.
1285 MockWrite data_writes2[] = {
1286 MockWrite("GET / HTTP/1.1\r\n"
1287 "Host: www.google.com\r\n"
1288 "Connection: keep-alive\r\n"
1289 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1290 };
1291
1292 // Lastly, the server responds with the actual content.
1293 MockRead data_reads2[] = {
1294 MockRead("HTTP/1.0 200 OK\r\n"),
1295 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1296 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421297 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161298 };
1299
[email protected]31a2bfe2010-02-09 08:03:391300 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1301 data_writes1, arraysize(data_writes1));
1302 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1303 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591304 session_deps.socket_factory.AddSocketDataProvider(&data1);
1305 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161306
[email protected]49639fa2011-12-20 23:22:411307 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:161308
[email protected]49639fa2011-12-20 23:22:411309 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421310 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161311
1312 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421313 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161314
[email protected]1c773ea12009-04-28 19:58:421315 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501316 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041317 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:161318
[email protected]49639fa2011-12-20 23:22:411319 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:161320
[email protected]49639fa2011-12-20 23:22:411321 rv = trans->RestartWithAuth(
1322 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421323 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161324
1325 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421326 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161327
1328 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501329 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:161330 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1331 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161332}
1333
[email protected]861fcd52009-08-26 02:33:461334TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461335 HttpRequestInfo request;
1336 request.method = "GET";
1337 request.url = GURL("http://www.google.com/");
1338 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1339
[email protected]cb9bf6ca2011-01-28 13:15:271340 SessionDependencies session_deps;
1341 scoped_ptr<HttpTransaction> trans(
1342 new HttpNetworkTransaction(CreateSession(&session_deps)));
1343
[email protected]861fcd52009-08-26 02:33:461344 MockWrite data_writes[] = {
1345 MockWrite("GET / HTTP/1.1\r\n"
1346 "Host: www.google.com\r\n"
1347 "Connection: keep-alive\r\n\r\n"),
1348 };
1349
1350 MockRead data_reads[] = {
1351 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1352 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1354 // Large content-length -- won't matter, as connection will be reset.
1355 MockRead("Content-Length: 10000\r\n\r\n"),
1356 MockRead(false, ERR_FAILED),
1357 };
1358
[email protected]31a2bfe2010-02-09 08:03:391359 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1360 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591361 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:411362 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:461363
[email protected]49639fa2011-12-20 23:22:411364 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461365 EXPECT_EQ(ERR_IO_PENDING, rv);
1366
1367 rv = callback.WaitForResult();
1368 EXPECT_EQ(0, rv);
1369
1370 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501371 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:461372 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1373}
1374
[email protected]2d2697f92009-02-18 21:00:321375// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1376// connection.
1377TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421378 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321379 request.method = "GET";
1380 request.url = GURL("http://www.google.com/");
1381 request.load_flags = 0;
1382
[email protected]cb9bf6ca2011-01-28 13:15:271383 SessionDependencies session_deps;
1384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1385
[email protected]2d2697f92009-02-18 21:00:321386 MockWrite data_writes1[] = {
1387 MockWrite("GET / HTTP/1.1\r\n"
1388 "Host: www.google.com\r\n"
1389 "Connection: keep-alive\r\n\r\n"),
1390
1391 // After calling trans->RestartWithAuth(), this is the request we should
1392 // be issuing -- the final header line contains the credentials.
1393 MockWrite("GET / HTTP/1.1\r\n"
1394 "Host: www.google.com\r\n"
1395 "Connection: keep-alive\r\n"
1396 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1397 };
1398
1399 MockRead data_reads1[] = {
1400 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1401 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1403 MockRead("Content-Length: 14\r\n\r\n"),
1404 MockRead("Unauthorized\r\n"),
1405
1406 // Lastly, the server responds with the actual content.
1407 MockRead("HTTP/1.1 200 OK\r\n"),
1408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501409 MockRead("Content-Length: 5\r\n\r\n"),
1410 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321411 };
1412
[email protected]2d0a4f92011-05-05 16:38:461413 // If there is a regression where we disconnect a Keep-Alive
1414 // connection during an auth roundtrip, we'll end up reading this.
1415 MockRead data_reads2[] = {
1416 MockRead(false, ERR_FAILED),
1417 };
1418
[email protected]31a2bfe2010-02-09 08:03:391419 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1420 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461421 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1422 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591423 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461424 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321425
[email protected]49639fa2011-12-20 23:22:411426 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321427
[email protected]0b0bf032010-09-21 18:08:501428 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411429 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421430 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321431
1432 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421433 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321434
[email protected]1c773ea12009-04-28 19:58:421435 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501436 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041437 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321438
[email protected]49639fa2011-12-20 23:22:411439 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321440
[email protected]49639fa2011-12-20 23:22:411441 rv = trans->RestartWithAuth(
1442 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421443 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321444
1445 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421446 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321447
1448 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501449 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321450 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501451 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321452}
1453
1454// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1455// connection and with no response body to drain.
1456TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421457 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321458 request.method = "GET";
1459 request.url = GURL("http://www.google.com/");
1460 request.load_flags = 0;
1461
[email protected]cb9bf6ca2011-01-28 13:15:271462 SessionDependencies session_deps;
1463 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1464
[email protected]2d2697f92009-02-18 21:00:321465 MockWrite data_writes1[] = {
1466 MockWrite("GET / HTTP/1.1\r\n"
1467 "Host: www.google.com\r\n"
1468 "Connection: keep-alive\r\n\r\n"),
1469
1470 // After calling trans->RestartWithAuth(), this is the request we should
1471 // be issuing -- the final header line contains the credentials.
1472 MockWrite("GET / HTTP/1.1\r\n"
1473 "Host: www.google.com\r\n"
1474 "Connection: keep-alive\r\n"
1475 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1476 };
1477
[email protected]2d2697f92009-02-18 21:00:321478 MockRead data_reads1[] = {
1479 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1480 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311481 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321482
1483 // Lastly, the server responds with the actual content.
1484 MockRead("HTTP/1.1 200 OK\r\n"),
1485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501486 MockRead("Content-Length: 5\r\n\r\n"),
1487 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321488 };
1489
[email protected]2d0a4f92011-05-05 16:38:461490 // An incorrect reconnect would cause this to be read.
1491 MockRead data_reads2[] = {
1492 MockRead(false, ERR_FAILED),
1493 };
1494
[email protected]31a2bfe2010-02-09 08:03:391495 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1496 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461497 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1498 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591499 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461500 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321501
[email protected]49639fa2011-12-20 23:22:411502 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321503
[email protected]0b0bf032010-09-21 18:08:501504 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411505 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421506 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321507
1508 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421509 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321510
[email protected]1c773ea12009-04-28 19:58:421511 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501512 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041513 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321514
[email protected]49639fa2011-12-20 23:22:411515 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321516
[email protected]49639fa2011-12-20 23:22:411517 rv = trans->RestartWithAuth(
1518 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421519 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321520
1521 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421522 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321523
1524 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501525 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321526 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501527 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321528}
1529
1530// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1531// connection and with a large response body to drain.
1532TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421533 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321534 request.method = "GET";
1535 request.url = GURL("http://www.google.com/");
1536 request.load_flags = 0;
1537
[email protected]cb9bf6ca2011-01-28 13:15:271538 SessionDependencies session_deps;
1539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1540
[email protected]2d2697f92009-02-18 21:00:321541 MockWrite data_writes1[] = {
1542 MockWrite("GET / HTTP/1.1\r\n"
1543 "Host: www.google.com\r\n"
1544 "Connection: keep-alive\r\n\r\n"),
1545
1546 // After calling trans->RestartWithAuth(), this is the request we should
1547 // be issuing -- the final header line contains the credentials.
1548 MockWrite("GET / HTTP/1.1\r\n"
1549 "Host: www.google.com\r\n"
1550 "Connection: keep-alive\r\n"
1551 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1552 };
1553
1554 // Respond with 5 kb of response body.
1555 std::string large_body_string("Unauthorized");
1556 large_body_string.append(5 * 1024, ' ');
1557 large_body_string.append("\r\n");
1558
1559 MockRead data_reads1[] = {
1560 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1561 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1562 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1563 // 5134 = 12 + 5 * 1024 + 2
1564 MockRead("Content-Length: 5134\r\n\r\n"),
1565 MockRead(true, large_body_string.data(), large_body_string.size()),
1566
1567 // Lastly, the server responds with the actual content.
1568 MockRead("HTTP/1.1 200 OK\r\n"),
1569 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501570 MockRead("Content-Length: 5\r\n\r\n"),
1571 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321572 };
1573
[email protected]2d0a4f92011-05-05 16:38:461574 // An incorrect reconnect would cause this to be read.
1575 MockRead data_reads2[] = {
1576 MockRead(false, ERR_FAILED),
1577 };
1578
[email protected]31a2bfe2010-02-09 08:03:391579 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1580 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461581 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1582 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591583 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461584 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321585
[email protected]49639fa2011-12-20 23:22:411586 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321587
[email protected]0b0bf032010-09-21 18:08:501588 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411589 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421590 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321591
1592 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421593 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321594
[email protected]1c773ea12009-04-28 19:58:421595 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501596 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041597 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321598
[email protected]49639fa2011-12-20 23:22:411599 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321600
[email protected]49639fa2011-12-20 23:22:411601 rv = trans->RestartWithAuth(
1602 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421603 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321604
1605 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421606 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321607
1608 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501609 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321610 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501611 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321612}
1613
1614// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311615// connection, but the server gets impatient and closes the connection.
1616TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311617 HttpRequestInfo request;
1618 request.method = "GET";
1619 request.url = GURL("http://www.google.com/");
1620 request.load_flags = 0;
1621
[email protected]cb9bf6ca2011-01-28 13:15:271622 SessionDependencies session_deps;
1623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1624
[email protected]11203f012009-11-12 23:02:311625 MockWrite data_writes1[] = {
1626 MockWrite("GET / HTTP/1.1\r\n"
1627 "Host: www.google.com\r\n"
1628 "Connection: keep-alive\r\n\r\n"),
1629 // This simulates the seemingly successful write to a closed connection
1630 // if the bug is not fixed.
1631 MockWrite("GET / HTTP/1.1\r\n"
1632 "Host: www.google.com\r\n"
1633 "Connection: keep-alive\r\n"
1634 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1635 };
1636
1637 MockRead data_reads1[] = {
1638 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1639 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1640 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1641 MockRead("Content-Length: 14\r\n\r\n"),
1642 // Tell MockTCPClientSocket to simulate the server closing the connection.
1643 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1644 MockRead("Unauthorized\r\n"),
1645 MockRead(false, OK), // The server closes the connection.
1646 };
1647
1648 // After calling trans->RestartWithAuth(), this is the request we should
1649 // be issuing -- the final header line contains the credentials.
1650 MockWrite data_writes2[] = {
1651 MockWrite("GET / HTTP/1.1\r\n"
1652 "Host: www.google.com\r\n"
1653 "Connection: keep-alive\r\n"
1654 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1655 };
1656
1657 // Lastly, the server responds with the actual content.
1658 MockRead data_reads2[] = {
1659 MockRead("HTTP/1.1 200 OK\r\n"),
1660 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501661 MockRead("Content-Length: 5\r\n\r\n"),
1662 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311663 };
1664
[email protected]31a2bfe2010-02-09 08:03:391665 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1666 data_writes1, arraysize(data_writes1));
1667 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1668 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311669 session_deps.socket_factory.AddSocketDataProvider(&data1);
1670 session_deps.socket_factory.AddSocketDataProvider(&data2);
1671
[email protected]49639fa2011-12-20 23:22:411672 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:311673
[email protected]0b0bf032010-09-21 18:08:501674 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411675 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:311676 EXPECT_EQ(ERR_IO_PENDING, rv);
1677
1678 rv = callback1.WaitForResult();
1679 EXPECT_EQ(OK, rv);
1680
1681 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501682 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041683 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:311684
[email protected]49639fa2011-12-20 23:22:411685 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:311686
[email protected]49639fa2011-12-20 23:22:411687 rv = trans->RestartWithAuth(
1688 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:311689 EXPECT_EQ(ERR_IO_PENDING, rv);
1690
1691 rv = callback2.WaitForResult();
1692 EXPECT_EQ(OK, rv);
1693
1694 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501695 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:311696 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501697 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311698}
1699
[email protected]394816e92010-08-03 07:38:591700// Test the request-challenge-retry sequence for basic auth, over a connection
1701// that requires a restart when setting up an SSL tunnel.
1702TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591703 HttpRequestInfo request;
1704 request.method = "GET";
1705 request.url = GURL("https://www.google.com/");
1706 // when the no authentication data flag is set.
1707 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1708
[email protected]cb9bf6ca2011-01-28 13:15:271709 // Configure against proxy server "myproxy:70".
1710 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1711 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1712 session_deps.net_log = log.bound().net_log();
1713 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1714
[email protected]394816e92010-08-03 07:38:591715 // Since we have proxy, should try to establish tunnel.
1716 MockWrite data_writes1[] = {
1717 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1718 "Host: www.google.com\r\n"
1719 "Proxy-Connection: keep-alive\r\n\r\n"),
1720
1721 // After calling trans->RestartWithAuth(), this is the request we should
1722 // be issuing -- the final header line contains the credentials.
1723 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1724 "Host: www.google.com\r\n"
1725 "Proxy-Connection: keep-alive\r\n"
1726 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1727
1728 MockWrite("GET / HTTP/1.1\r\n"
1729 "Host: www.google.com\r\n"
1730 "Connection: keep-alive\r\n\r\n"),
1731 };
1732
1733 // The proxy responds to the connect with a 407, using a persistent
1734 // connection.
1735 MockRead data_reads1[] = {
1736 // No credentials.
1737 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1738 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1739 MockRead("Proxy-Connection: close\r\n\r\n"),
1740
1741 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1742
1743 MockRead("HTTP/1.1 200 OK\r\n"),
1744 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501745 MockRead("Content-Length: 5\r\n\r\n"),
1746 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591747 };
1748
1749 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1750 data_writes1, arraysize(data_writes1));
1751 session_deps.socket_factory.AddSocketDataProvider(&data1);
1752 SSLSocketDataProvider ssl(true, OK);
1753 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1754
[email protected]49639fa2011-12-20 23:22:411755 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:591756
[email protected]0b0bf032010-09-21 18:08:501757 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1758
[email protected]49639fa2011-12-20 23:22:411759 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:591760 EXPECT_EQ(ERR_IO_PENDING, rv);
1761
1762 rv = callback1.WaitForResult();
1763 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401764 net::CapturingNetLog::EntryList entries;
1765 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591766 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401767 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591768 NetLog::PHASE_NONE);
1769 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401770 entries, pos,
[email protected]394816e92010-08-03 07:38:591771 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1772 NetLog::PHASE_NONE);
1773
1774 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501775 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041776 ASSERT_FALSE(response->headers == NULL);
[email protected]394816e92010-08-03 07:38:591777 EXPECT_EQ(407, response->headers->response_code());
1778 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041779 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:591780
[email protected]49639fa2011-12-20 23:22:411781 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:591782
[email protected]49639fa2011-12-20 23:22:411783 rv = trans->RestartWithAuth(
1784 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:591785 EXPECT_EQ(ERR_IO_PENDING, rv);
1786
1787 rv = callback2.WaitForResult();
1788 EXPECT_EQ(OK, rv);
1789
1790 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501791 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:591792
1793 EXPECT_TRUE(response->headers->IsKeepAlive());
1794 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501795 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591796 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1797
1798 // The password prompt info should not be set.
1799 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501800
1801 trans.reset();
[email protected]102e27c2011-02-23 01:01:311802 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591803}
1804
[email protected]11203f012009-11-12 23:02:311805// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321806// proxy connection, when setting up an SSL tunnel.
1807TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271808 HttpRequestInfo request;
1809 request.method = "GET";
1810 request.url = GURL("https://www.google.com/");
1811 // Ensure that proxy authentication is attempted even
1812 // when the no authentication data flag is set.
1813 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1814
[email protected]2d2697f92009-02-18 21:00:321815 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001816 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541817 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1818 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591819 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321820
[email protected]5695b8c2009-09-30 21:36:431821 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321822
[email protected]2d2697f92009-02-18 21:00:321823 // Since we have proxy, should try to establish tunnel.
1824 MockWrite data_writes1[] = {
1825 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451826 "Host: www.google.com\r\n"
1827 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321828
1829 // After calling trans->RestartWithAuth(), this is the request we should
1830 // be issuing -- the final header line contains the credentials.
1831 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1832 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451833 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321834 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1835 };
1836
1837 // The proxy responds to the connect with a 407, using a persistent
1838 // connection.
1839 MockRead data_reads1[] = {
1840 // No credentials.
1841 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1842 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1843 MockRead("Content-Length: 10\r\n\r\n"),
1844 MockRead("0123456789"),
1845
1846 // Wrong credentials (wrong password).
1847 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1848 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1849 MockRead("Content-Length: 10\r\n\r\n"),
1850 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421851 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321852 };
1853
[email protected]31a2bfe2010-02-09 08:03:391854 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1855 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591856 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321857
[email protected]49639fa2011-12-20 23:22:411858 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321859
[email protected]49639fa2011-12-20 23:22:411860 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]1c773ea12009-04-28 19:58:421861 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321862
1863 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421864 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401865 net::CapturingNetLog::EntryList entries;
1866 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391867 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401868 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391869 NetLog::PHASE_NONE);
1870 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401871 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391872 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1873 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321874
[email protected]1c773ea12009-04-28 19:58:421875 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501876 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041877 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321878 EXPECT_TRUE(response->headers->IsKeepAlive());
1879 EXPECT_EQ(407, response->headers->response_code());
1880 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421881 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041882 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321883
[email protected]49639fa2011-12-20 23:22:411884 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321885
1886 // Wrong password (should be "bar").
[email protected]49639fa2011-12-20 23:22:411887 rv = trans->RestartWithAuth(
1888 AuthCredentials(kFoo, kBaz), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421889 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321890
1891 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421892 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321893
1894 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501895 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041896 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321897 EXPECT_TRUE(response->headers->IsKeepAlive());
1898 EXPECT_EQ(407, response->headers->response_code());
1899 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421900 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041901 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]e772db3f2010-07-12 18:11:131902
[email protected]e60e47a2010-07-14 03:37:181903 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1904 // out of scope.
[email protected]102e27c2011-02-23 01:01:311905 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321906}
1907
[email protected]a8e9b162009-03-12 00:06:441908// Test that we don't read the response body when we fail to establish a tunnel,
1909// even if the user cancels the proxy's auth attempt.
1910TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271911 HttpRequestInfo request;
1912 request.method = "GET";
1913 request.url = GURL("https://www.google.com/");
1914 request.load_flags = 0;
1915
[email protected]a8e9b162009-03-12 00:06:441916 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001917 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441918
[email protected]e44de5d2009-06-05 20:12:451919 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441920
[email protected]5695b8c2009-09-30 21:36:431921 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441922
[email protected]a8e9b162009-03-12 00:06:441923 // Since we have proxy, should try to establish tunnel.
1924 MockWrite data_writes[] = {
1925 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451926 "Host: www.google.com\r\n"
1927 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441928 };
1929
1930 // The proxy responds to the connect with a 407.
1931 MockRead data_reads[] = {
1932 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1933 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1934 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421935 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441936 };
1937
[email protected]31a2bfe2010-02-09 08:03:391938 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1939 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591940 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441941
[email protected]49639fa2011-12-20 23:22:411942 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:441943
[email protected]49639fa2011-12-20 23:22:411944 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421945 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441946
1947 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421948 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441949
[email protected]1c773ea12009-04-28 19:58:421950 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501951 ASSERT_TRUE(response != NULL);
[email protected]a8e9b162009-03-12 00:06:441952
1953 EXPECT_TRUE(response->headers->IsKeepAlive());
1954 EXPECT_EQ(407, response->headers->response_code());
1955 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421956 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441957
1958 std::string response_data;
1959 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421960 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181961
1962 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311963 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441964}
1965
[email protected]8fdbcd22010-05-05 02:54:521966// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1967// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1968TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521969 HttpRequestInfo request;
1970 request.method = "GET";
1971 request.url = GURL("http://www.google.com/");
1972 request.load_flags = 0;
1973
[email protected]cb9bf6ca2011-01-28 13:15:271974 // We are using a DIRECT connection (i.e. no proxy) for this session.
1975 SessionDependencies session_deps;
1976 scoped_ptr<HttpTransaction> trans(
1977 new HttpNetworkTransaction(CreateSession(&session_deps)));
1978
[email protected]8fdbcd22010-05-05 02:54:521979 MockWrite data_writes1[] = {
1980 MockWrite("GET / HTTP/1.1\r\n"
1981 "Host: www.google.com\r\n"
1982 "Connection: keep-alive\r\n\r\n"),
1983 };
1984
1985 MockRead data_reads1[] = {
1986 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1987 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1988 // Large content-length -- won't matter, as connection will be reset.
1989 MockRead("Content-Length: 10000\r\n\r\n"),
1990 MockRead(false, ERR_FAILED),
1991 };
1992
1993 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1994 data_writes1, arraysize(data_writes1));
1995 session_deps.socket_factory.AddSocketDataProvider(&data1);
1996
[email protected]49639fa2011-12-20 23:22:411997 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:521998
[email protected]49639fa2011-12-20 23:22:411999 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:522000 EXPECT_EQ(ERR_IO_PENDING, rv);
2001
2002 rv = callback.WaitForResult();
2003 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2004}
2005
[email protected]7a67a8152010-11-05 18:31:102006// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2007// through a non-authenticating proxy. The request should fail with
2008// ERR_UNEXPECTED_PROXY_AUTH.
2009// Note that it is impossible to detect if an HTTP server returns a 407 through
2010// a non-authenticating proxy - there is nothing to indicate whether the
2011// response came from the proxy or the server, so it is treated as if the proxy
2012// issued the challenge.
2013TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:272014 HttpRequestInfo request;
2015 request.method = "GET";
2016 request.url = GURL("https://www.google.com/");
2017
[email protected]7a67a8152010-11-05 18:31:102018 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2019 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2020 session_deps.net_log = log.bound().net_log();
2021 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2022
[email protected]7a67a8152010-11-05 18:31:102023 // Since we have proxy, should try to establish tunnel.
2024 MockWrite data_writes1[] = {
2025 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2026 "Host: www.google.com\r\n"
2027 "Proxy-Connection: keep-alive\r\n\r\n"),
2028
2029 MockWrite("GET / HTTP/1.1\r\n"
2030 "Host: www.google.com\r\n"
2031 "Connection: keep-alive\r\n\r\n"),
2032 };
2033
2034 MockRead data_reads1[] = {
2035 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2036
2037 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2038 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2039 MockRead("\r\n"),
2040 MockRead(false, OK),
2041 };
2042
2043 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2044 data_writes1, arraysize(data_writes1));
2045 session_deps.socket_factory.AddSocketDataProvider(&data1);
2046 SSLSocketDataProvider ssl(true, OK);
2047 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2048
[email protected]49639fa2011-12-20 23:22:412049 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:102050
2051 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2052
[email protected]49639fa2011-12-20 23:22:412053 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:102054 EXPECT_EQ(ERR_IO_PENDING, rv);
2055
2056 rv = callback1.WaitForResult();
2057 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:402058 net::CapturingNetLog::EntryList entries;
2059 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:102060 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402061 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:102062 NetLog::PHASE_NONE);
2063 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402064 entries, pos,
[email protected]7a67a8152010-11-05 18:31:102065 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2066 NetLog::PHASE_NONE);
2067}
[email protected]2df19bb2010-08-25 20:13:462068
2069// Test a simple get through an HTTPS Proxy.
2070TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272071 HttpRequestInfo request;
2072 request.method = "GET";
2073 request.url = GURL("http://www.google.com/");
2074
[email protected]2df19bb2010-08-25 20:13:462075 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112076 SessionDependencies session_deps(ProxyService::CreateFixed(
2077 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462078 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2079 session_deps.net_log = log.bound().net_log();
2080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2081
[email protected]2df19bb2010-08-25 20:13:462082 // Since we have proxy, should use full url
2083 MockWrite data_writes1[] = {
2084 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2085 "Host: www.google.com\r\n"
2086 "Proxy-Connection: keep-alive\r\n\r\n"),
2087 };
2088
2089 MockRead data_reads1[] = {
2090 MockRead("HTTP/1.1 200 OK\r\n"),
2091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2092 MockRead("Content-Length: 100\r\n\r\n"),
2093 MockRead(false, OK),
2094 };
2095
2096 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2097 data_writes1, arraysize(data_writes1));
2098 session_deps.socket_factory.AddSocketDataProvider(&data1);
2099 SSLSocketDataProvider ssl(true, OK);
2100 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2101
[email protected]49639fa2011-12-20 23:22:412102 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462103
[email protected]0b0bf032010-09-21 18:08:502104 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2105
[email protected]49639fa2011-12-20 23:22:412106 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:462107 EXPECT_EQ(ERR_IO_PENDING, rv);
2108
2109 rv = callback1.WaitForResult();
2110 EXPECT_EQ(OK, rv);
2111
2112 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502113 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462114
2115 EXPECT_TRUE(response->headers->IsKeepAlive());
2116 EXPECT_EQ(200, response->headers->response_code());
2117 EXPECT_EQ(100, response->headers->GetContentLength());
2118 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2119
2120 // The password prompt info should not be set.
2121 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2122}
2123
[email protected]7642b5ae2010-09-01 20:55:172124// Test a SPDY get through an HTTPS Proxy.
2125TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272126 HttpRequestInfo request;
2127 request.method = "GET";
2128 request.url = GURL("http://www.google.com/");
2129 request.load_flags = 0;
2130
[email protected]7642b5ae2010-09-01 20:55:172131 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112132 SessionDependencies session_deps(ProxyService::CreateFixed(
2133 "https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:172134 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2135 session_deps.net_log = log.bound().net_log();
2136 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2137
[email protected]7642b5ae2010-09-01 20:55:172138 // fetch http://www.google.com/ via SPDY
2139 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
2140 false));
2141 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2142
2143 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2144 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2145 MockRead spdy_reads[] = {
2146 CreateMockRead(*resp),
2147 CreateMockRead(*data),
2148 MockRead(true, 0, 0),
2149 };
2150
[email protected]a1595312012-01-22 03:25:042151 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]7642b5ae2010-09-01 20:55:172152 new DelayedSocketData(
2153 1, // wait for one write to finish before reading.
2154 spdy_reads, arraysize(spdy_reads),
2155 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042156 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]7642b5ae2010-09-01 20:55:172157
2158 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:512159 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]7642b5ae2010-09-01 20:55:172160 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2161
[email protected]49639fa2011-12-20 23:22:412162 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:172163
[email protected]0b0bf032010-09-21 18:08:502164 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2165
[email protected]49639fa2011-12-20 23:22:412166 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:172167 EXPECT_EQ(ERR_IO_PENDING, rv);
2168
2169 rv = callback1.WaitForResult();
2170 EXPECT_EQ(OK, rv);
2171
2172 const HttpResponseInfo* response = trans->GetResponseInfo();
2173 ASSERT_TRUE(response != NULL);
2174 ASSERT_TRUE(response->headers != NULL);
2175 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2176
2177 std::string response_data;
2178 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2179 EXPECT_EQ(net::kUploadData, response_data);
2180}
2181
[email protected]dc7bd1c52010-11-12 00:01:132182// Test a SPDY get through an HTTPS Proxy.
2183TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272184 HttpRequestInfo request;
2185 request.method = "GET";
2186 request.url = GURL("http://www.google.com/");
2187 request.load_flags = 0;
2188
[email protected]79cb5c12011-09-12 13:12:042189 // Configure against https proxy server "myproxy:70".
[email protected]dc7bd1c52010-11-12 00:01:132190 SessionDependencies session_deps(
[email protected]79cb5c12011-09-12 13:12:042191 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]dc7bd1c52010-11-12 00:01:132192 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2193 session_deps.net_log = log.bound().net_log();
2194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2195
[email protected]dc7bd1c52010-11-12 00:01:132196 // The first request will be a bare GET, the second request will be a
2197 // GET with a Proxy-Authorization header.
2198 scoped_ptr<spdy::SpdyFrame> req_get(
2199 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2200 const char* const kExtraAuthorizationHeaders[] = {
2201 "proxy-authorization",
2202 "Basic Zm9vOmJhcg==",
2203 };
2204 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2205 ConstructSpdyGet(
2206 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2207 false, 3, LOWEST, false));
2208 MockWrite spdy_writes[] = {
2209 CreateMockWrite(*req_get, 1),
2210 CreateMockWrite(*req_get_authorization, 4),
2211 };
2212
2213 // The first response is a 407 proxy authentication challenge, and the second
2214 // response will be a 200 response since the second request includes a valid
2215 // Authorization header.
2216 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:262217 "proxy-authenticate",
[email protected]dc7bd1c52010-11-12 00:01:132218 "Basic realm=\"MyRealm1\""
2219 };
2220 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2221 ConstructSpdySynReplyError(
2222 "407 Proxy Authentication Required",
2223 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2224 1));
2225 scoped_ptr<spdy::SpdyFrame> body_authentication(
2226 ConstructSpdyBodyFrame(1, true));
2227 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2228 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2229 MockRead spdy_reads[] = {
2230 CreateMockRead(*resp_authentication, 2),
2231 CreateMockRead(*body_authentication, 3),
2232 CreateMockRead(*resp_data, 5),
2233 CreateMockRead(*body_data, 6),
2234 MockRead(true, 0, 7),
2235 };
2236
[email protected]a1595312012-01-22 03:25:042237 scoped_ptr<OrderedSocketData> data(
[email protected]dc7bd1c52010-11-12 00:01:132238 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2239 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042240 session_deps.socket_factory.AddSocketDataProvider(data.get());
[email protected]dc7bd1c52010-11-12 00:01:132241
2242 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:512243 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]dc7bd1c52010-11-12 00:01:132244 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2245
[email protected]49639fa2011-12-20 23:22:412246 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:132247
2248 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2249
[email protected]49639fa2011-12-20 23:22:412250 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:132251 EXPECT_EQ(ERR_IO_PENDING, rv);
2252
2253 rv = callback1.WaitForResult();
2254 EXPECT_EQ(OK, rv);
2255
2256 const HttpResponseInfo* const response = trans->GetResponseInfo();
2257
2258 ASSERT_TRUE(response != NULL);
2259 ASSERT_TRUE(response->headers != NULL);
2260 EXPECT_EQ(407, response->headers->response_code());
2261 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:042262 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:132263
[email protected]49639fa2011-12-20 23:22:412264 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:132265
[email protected]49639fa2011-12-20 23:22:412266 rv = trans->RestartWithAuth(
2267 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:132268 EXPECT_EQ(ERR_IO_PENDING, rv);
2269
2270 rv = callback2.WaitForResult();
2271 EXPECT_EQ(OK, rv);
2272
2273 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2274
2275 ASSERT_TRUE(response_restart != NULL);
2276 ASSERT_TRUE(response_restart->headers != NULL);
2277 EXPECT_EQ(200, response_restart->headers->response_code());
2278 // The password prompt info should not be set.
2279 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2280}
2281
[email protected]d9da5fe2010-10-13 22:37:162282// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2283TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272284 HttpRequestInfo request;
2285 request.method = "GET";
2286 request.url = GURL("https://www.google.com/");
2287 request.load_flags = 0;
2288
[email protected]d9da5fe2010-10-13 22:37:162289 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112290 SessionDependencies session_deps(ProxyService::CreateFixed(
2291 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162292 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2293 session_deps.net_log = log.bound().net_log();
2294 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2295
2296 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2297
[email protected]d9da5fe2010-10-13 22:37:162298 // CONNECT to www.google.com:443 via SPDY
2299 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2300 // fetch https://www.google.com/ via HTTP
2301
2302 const char get[] = "GET / HTTP/1.1\r\n"
2303 "Host: www.google.com\r\n"
2304 "Connection: keep-alive\r\n\r\n";
2305 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2306 ConstructSpdyBodyFrame(1, get, strlen(get), false));
[email protected]d9da5fe2010-10-13 22:37:162307 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2308 const char resp[] = "HTTP/1.1 200 OK\r\n"
2309 "Content-Length: 10\r\n\r\n";
[email protected]d9da5fe2010-10-13 22:37:162310 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2311 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2312 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2313 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]8d2f7012012-02-16 00:08:042314 scoped_ptr<spdy::SpdyFrame> window_update(
2315 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2316
2317 MockWrite spdy_writes[] = {
2318 CreateMockWrite(*connect, 1),
2319 CreateMockWrite(*wrapped_get, 3),
2320 CreateMockWrite(*window_update, 5)
2321 };
2322
[email protected]d9da5fe2010-10-13 22:37:162323 MockRead spdy_reads[] = {
2324 CreateMockRead(*conn_resp, 2, true),
2325 CreateMockRead(*wrapped_get_resp, 4, true),
[email protected]d9da5fe2010-10-13 22:37:162326 CreateMockRead(*wrapped_body, 6, true),
[email protected]8d2f7012012-02-16 00:08:042327 CreateMockRead(*wrapped_body, 7, true),
2328 MockRead(true, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:162329 };
2330
[email protected]a1595312012-01-22 03:25:042331 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162332 new OrderedSocketData(
2333 spdy_reads, arraysize(spdy_reads),
2334 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042335 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162336
2337 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:512338 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162339 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2340 SSLSocketDataProvider ssl2(true, OK);
2341 ssl2.was_npn_negotiated = false;
[email protected]c30bcce2011-12-20 17:50:512342 ssl2.protocol_negotiated = SSLClientSocket::kProtoUnknown;
[email protected]d9da5fe2010-10-13 22:37:162343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2344
[email protected]49639fa2011-12-20 23:22:412345 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162346
[email protected]49639fa2011-12-20 23:22:412347 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162348 EXPECT_EQ(ERR_IO_PENDING, rv);
2349
2350 rv = callback1.WaitForResult();
2351 EXPECT_EQ(OK, rv);
2352
2353 const HttpResponseInfo* response = trans->GetResponseInfo();
2354 ASSERT_TRUE(response != NULL);
2355 ASSERT_TRUE(response->headers != NULL);
2356 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2357
2358 std::string response_data;
2359 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2360 EXPECT_EQ("1234567890", response_data);
2361}
2362
2363// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2364TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272365 HttpRequestInfo request;
2366 request.method = "GET";
2367 request.url = GURL("https://www.google.com/");
2368 request.load_flags = 0;
2369
[email protected]d9da5fe2010-10-13 22:37:162370 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112371 SessionDependencies session_deps(ProxyService::CreateFixed(
2372 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162373 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2374 session_deps.net_log = log.bound().net_log();
2375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2376
2377 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2378
[email protected]d9da5fe2010-10-13 22:37:162379 // CONNECT to www.google.com:443 via SPDY
2380 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2381 // fetch https://www.google.com/ via SPDY
2382 const char* const kMyUrl = "https://www.google.com/";
2383 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2384 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
[email protected]d9da5fe2010-10-13 22:37:162385 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2386 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2387 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2388 ConstructWrappedSpdyFrame(get_resp, 1));
2389 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2390 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
[email protected]8d2f7012012-02-16 00:08:042391 scoped_ptr<spdy::SpdyFrame> window_update_get_resp(
2392 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2393 scoped_ptr<spdy::SpdyFrame> window_update_body(
2394 ConstructSpdyWindowUpdate(1, wrapped_body->length()));
2395
2396 MockWrite spdy_writes[] = {
2397 CreateMockWrite(*connect, 1),
2398 CreateMockWrite(*wrapped_get, 3),
2399 CreateMockWrite(*window_update_get_resp, 5),
2400 CreateMockWrite(*window_update_body, 7),
2401 };
2402
[email protected]d9da5fe2010-10-13 22:37:162403 MockRead spdy_reads[] = {
2404 CreateMockRead(*conn_resp, 2, true),
2405 CreateMockRead(*wrapped_get_resp, 4, true),
[email protected]8d2f7012012-02-16 00:08:042406 CreateMockRead(*wrapped_body, 6, true),
2407 MockRead(true, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:162408 };
2409
[email protected]a1595312012-01-22 03:25:042410 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162411 new OrderedSocketData(
2412 spdy_reads, arraysize(spdy_reads),
2413 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042414 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162415
2416 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:512417 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162418 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2419 SSLSocketDataProvider ssl2(true, OK);
[email protected]e58c1b82012-02-22 23:07:512420 ssl2.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]1ad77dc2012-01-27 03:51:202421 ssl2.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162422 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2423
[email protected]49639fa2011-12-20 23:22:412424 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162425
[email protected]49639fa2011-12-20 23:22:412426 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162427 EXPECT_EQ(ERR_IO_PENDING, rv);
2428
2429 rv = callback1.WaitForResult();
2430 EXPECT_EQ(OK, rv);
2431
2432 const HttpResponseInfo* response = trans->GetResponseInfo();
2433 ASSERT_TRUE(response != NULL);
2434 ASSERT_TRUE(response->headers != NULL);
2435 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2436
2437 std::string response_data;
2438 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2439 EXPECT_EQ(net::kUploadData, response_data);
2440}
2441
2442// Test a SPDY CONNECT failure through an HTTPS Proxy.
2443TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272444 HttpRequestInfo request;
2445 request.method = "GET";
2446 request.url = GURL("https://www.google.com/");
2447 request.load_flags = 0;
2448
[email protected]d9da5fe2010-10-13 22:37:162449 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112450 SessionDependencies session_deps(ProxyService::CreateFixed(
2451 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162452 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2453 session_deps.net_log = log.bound().net_log();
2454 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2455
2456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2457
[email protected]d9da5fe2010-10-13 22:37:162458 // CONNECT to www.google.com:443 via SPDY
2459 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2460 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2461
2462 MockWrite spdy_writes[] = {
2463 CreateMockWrite(*connect, 1),
2464 CreateMockWrite(*get, 3),
2465 };
2466
2467 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2468 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2469 MockRead spdy_reads[] = {
2470 CreateMockRead(*resp, 2, true),
2471 MockRead(true, 0, 4),
2472 };
2473
[email protected]a1595312012-01-22 03:25:042474 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162475 new OrderedSocketData(
2476 spdy_reads, arraysize(spdy_reads),
2477 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042478 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162479
2480 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:512481 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162482 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2483 SSLSocketDataProvider ssl2(true, OK);
[email protected]e58c1b82012-02-22 23:07:512484 ssl2.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162485 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2486
[email protected]49639fa2011-12-20 23:22:412487 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162488
[email protected]49639fa2011-12-20 23:22:412489 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162490 EXPECT_EQ(ERR_IO_PENDING, rv);
2491
2492 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292493 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162494
2495 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502496 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:292497 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162498}
2499
[email protected]2df19bb2010-08-25 20:13:462500// Test the challenge-response-retry sequence through an HTTPS Proxy
2501TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462502 HttpRequestInfo request;
2503 request.method = "GET";
2504 request.url = GURL("http://www.google.com/");
2505 // when the no authentication data flag is set.
2506 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2507
[email protected]79cb5c12011-09-12 13:12:042508 // Configure against https proxy server "myproxy:70".
2509 SessionDependencies session_deps(
2510 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]cb9bf6ca2011-01-28 13:15:272511 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2512 session_deps.net_log = log.bound().net_log();
2513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2514
[email protected]2df19bb2010-08-25 20:13:462515 // Since we have proxy, should use full url
2516 MockWrite data_writes1[] = {
2517 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2518 "Host: www.google.com\r\n"
2519 "Proxy-Connection: keep-alive\r\n\r\n"),
2520
2521 // After calling trans->RestartWithAuth(), this is the request we should
2522 // be issuing -- the final header line contains the credentials.
2523 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2524 "Host: www.google.com\r\n"
2525 "Proxy-Connection: keep-alive\r\n"
2526 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2527 };
2528
2529 // The proxy responds to the GET with a 407, using a persistent
2530 // connection.
2531 MockRead data_reads1[] = {
2532 // No credentials.
2533 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2534 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2535 MockRead("Proxy-Connection: keep-alive\r\n"),
2536 MockRead("Content-Length: 0\r\n\r\n"),
2537
2538 MockRead("HTTP/1.1 200 OK\r\n"),
2539 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2540 MockRead("Content-Length: 100\r\n\r\n"),
2541 MockRead(false, OK),
2542 };
2543
2544 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2545 data_writes1, arraysize(data_writes1));
2546 session_deps.socket_factory.AddSocketDataProvider(&data1);
2547 SSLSocketDataProvider ssl(true, OK);
2548 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2549
[email protected]49639fa2011-12-20 23:22:412550 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462551
[email protected]0b0bf032010-09-21 18:08:502552 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2553
[email protected]49639fa2011-12-20 23:22:412554 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:462555 EXPECT_EQ(ERR_IO_PENDING, rv);
2556
2557 rv = callback1.WaitForResult();
2558 EXPECT_EQ(OK, rv);
2559
2560 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502561 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042562 ASSERT_FALSE(response->headers == NULL);
[email protected]2df19bb2010-08-25 20:13:462563 EXPECT_EQ(407, response->headers->response_code());
2564 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042565 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:462566
[email protected]49639fa2011-12-20 23:22:412567 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:462568
[email protected]49639fa2011-12-20 23:22:412569 rv = trans->RestartWithAuth(
2570 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:462571 EXPECT_EQ(ERR_IO_PENDING, rv);
2572
2573 rv = callback2.WaitForResult();
2574 EXPECT_EQ(OK, rv);
2575
2576 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502577 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462578
2579 EXPECT_TRUE(response->headers->IsKeepAlive());
2580 EXPECT_EQ(200, response->headers->response_code());
2581 EXPECT_EQ(100, response->headers->GetContentLength());
2582 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2583
2584 // The password prompt info should not be set.
2585 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2586}
2587
[email protected]ff007e162009-05-23 09:13:152588void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082589 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422590 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082591 request.method = "GET";
2592 request.url = GURL("https://www.google.com/");
2593 request.load_flags = 0;
2594
[email protected]cb9bf6ca2011-01-28 13:15:272595 // Configure against proxy server "myproxy:70".
2596 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2597
2598 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2599
[email protected]c744cf22009-02-27 07:28:082600 // Since we have proxy, should try to establish tunnel.
2601 MockWrite data_writes[] = {
2602 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452603 "Host: www.google.com\r\n"
2604 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082605 };
2606
2607 MockRead data_reads[] = {
2608 status,
2609 MockRead("Content-Length: 10\r\n\r\n"),
2610 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422611 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082612 };
2613
[email protected]31a2bfe2010-02-09 08:03:392614 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2615 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592616 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082617
[email protected]49639fa2011-12-20 23:22:412618 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:082619
[email protected]0b0bf032010-09-21 18:08:502620 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2621
[email protected]49639fa2011-12-20 23:22:412622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422623 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082624
2625 rv = callback.WaitForResult();
2626 EXPECT_EQ(expected_status, rv);
2627}
2628
[email protected]ff007e162009-05-23 09:13:152629void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082630 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422631 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082632}
2633
2634TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2635 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2636}
2637
2638TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2639 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2640}
2641
2642TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2643 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2644}
2645
2646TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2647 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2648}
2649
2650TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2651 ConnectStatusHelper(
2652 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2653}
2654
2655TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2656 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2657}
2658
2659TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2660 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2661}
2662
2663TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2664 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2665}
2666
2667TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2668 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2669}
2670
2671TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2672 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2673}
2674
2675TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2676 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2677}
2678
2679TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2680 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2681}
2682
2683TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2684 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2685}
2686
2687TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2688 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2689}
2690
2691TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2692 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2693}
2694
2695TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2696 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2697}
2698
2699TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2700 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2701}
2702
2703TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2704 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2705}
2706
2707TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2708 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2709}
2710
2711TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2712 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2713}
2714
2715TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2716 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2717}
2718
2719TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2720 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2721}
2722
2723TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2724 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2725}
2726
2727TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2728 ConnectStatusHelperWithExpectedStatus(
2729 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542730 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082731}
2732
2733TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2734 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2735}
2736
2737TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2738 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2739}
2740
2741TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2742 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2743}
2744
2745TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2746 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2747}
2748
2749TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2750 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2751}
2752
2753TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2754 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2755}
2756
2757TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2758 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2759}
2760
2761TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2762 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2763}
2764
2765TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2766 ConnectStatusHelper(
2767 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2768}
2769
2770TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2771 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2772}
2773
2774TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2775 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2776}
2777
2778TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2779 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2780}
2781
2782TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2783 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2784}
2785
2786TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2787 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2788}
2789
2790TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2791 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2792}
2793
2794TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2795 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2796}
2797
[email protected]038e9a32008-10-08 22:40:162798// Test the flow when both the proxy server AND origin server require
2799// authentication. Again, this uses basic auth for both since that is
2800// the simplest to mock.
2801TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272802 HttpRequestInfo request;
2803 request.method = "GET";
2804 request.url = GURL("http://www.google.com/");
2805 request.load_flags = 0;
2806
[email protected]81cdfcd2010-10-16 00:49:002807 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012808
[email protected]038e9a32008-10-08 22:40:162809 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422810 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432811 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162812
[email protected]f9ee6b52008-11-08 06:46:232813 MockWrite data_writes1[] = {
2814 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2815 "Host: www.google.com\r\n"
2816 "Proxy-Connection: keep-alive\r\n\r\n"),
2817 };
2818
[email protected]038e9a32008-10-08 22:40:162819 MockRead data_reads1[] = {
2820 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2821 // Give a couple authenticate options (only the middle one is actually
2822 // supported).
[email protected]22927ad2009-09-21 19:56:192823 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162824 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2825 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2826 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2827 // Large content-length -- won't matter, as connection will be reset.
2828 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422829 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162830 };
2831
2832 // After calling trans->RestartWithAuth() the first time, this is the
2833 // request we should be issuing -- the final header line contains the
2834 // proxy's credentials.
2835 MockWrite data_writes2[] = {
2836 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2837 "Host: www.google.com\r\n"
2838 "Proxy-Connection: keep-alive\r\n"
2839 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2840 };
2841
2842 // Now the proxy server lets the request pass through to origin server.
2843 // The origin server responds with a 401.
2844 MockRead data_reads2[] = {
2845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2846 // Note: We are using the same realm-name as the proxy server. This is
2847 // completely valid, as realms are unique across hosts.
2848 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2849 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2850 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422851 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162852 };
2853
2854 // After calling trans->RestartWithAuth() the second time, we should send
2855 // the credentials for both the proxy and origin server.
2856 MockWrite data_writes3[] = {
2857 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2858 "Host: www.google.com\r\n"
2859 "Proxy-Connection: keep-alive\r\n"
2860 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2861 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2862 };
2863
2864 // Lastly we get the desired content.
2865 MockRead data_reads3[] = {
2866 MockRead("HTTP/1.0 200 OK\r\n"),
2867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2868 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422869 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162870 };
2871
[email protected]31a2bfe2010-02-09 08:03:392872 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2873 data_writes1, arraysize(data_writes1));
2874 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2875 data_writes2, arraysize(data_writes2));
2876 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2877 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592878 session_deps.socket_factory.AddSocketDataProvider(&data1);
2879 session_deps.socket_factory.AddSocketDataProvider(&data2);
2880 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162881
[email protected]49639fa2011-12-20 23:22:412882 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162883
[email protected]49639fa2011-12-20 23:22:412884 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162886
2887 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422888 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162889
[email protected]1c773ea12009-04-28 19:58:422890 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502891 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042892 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162893
[email protected]49639fa2011-12-20 23:22:412894 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162895
[email protected]49639fa2011-12-20 23:22:412896 rv = trans->RestartWithAuth(
2897 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162899
2900 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422901 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162902
2903 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502904 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042905 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162906
[email protected]49639fa2011-12-20 23:22:412907 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:162908
[email protected]49639fa2011-12-20 23:22:412909 rv = trans->RestartWithAuth(
2910 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:422911 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162912
2913 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422914 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162915
2916 response = trans->GetResponseInfo();
2917 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2918 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162919}
[email protected]4ddaf2502008-10-23 18:26:192920
[email protected]ea9dc9a2009-09-05 00:43:322921// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2922// can't hook into its internals to cause it to generate predictable NTLM
2923// authorization headers.
2924#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292925// The NTLM authentication unit tests were generated by capturing the HTTP
2926// requests and responses using Fiddler 2 and inspecting the generated random
2927// bytes in the debugger.
2928
2929// Enter the correct password and authenticate successfully.
2930TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422931 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242932 request.method = "GET";
2933 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2934 request.load_flags = 0;
2935
[email protected]cb9bf6ca2011-01-28 13:15:272936 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2937 MockGetHostName);
2938 SessionDependencies session_deps;
2939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2940
[email protected]3f918782009-02-28 01:29:242941 MockWrite data_writes1[] = {
2942 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2943 "Host: 172.22.68.17\r\n"
2944 "Connection: keep-alive\r\n\r\n"),
2945 };
2946
2947 MockRead data_reads1[] = {
2948 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042949 // Negotiate and NTLM are often requested together. However, we only want
2950 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2951 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242952 MockRead("WWW-Authenticate: NTLM\r\n"),
2953 MockRead("Connection: close\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 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422957 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242958 };
2959
2960 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222961 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242962 // request we should be issuing -- the final header line contains a Type
2963 // 1 message.
2964 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2965 "Host: 172.22.68.17\r\n"
2966 "Connection: keep-alive\r\n"
2967 "Authorization: NTLM "
2968 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2969
2970 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2971 // (the credentials for the origin server). The second request continues
2972 // on the same connection.
2973 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2974 "Host: 172.22.68.17\r\n"
2975 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292976 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2977 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2978 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2979 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2980 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242981 };
2982
2983 MockRead data_reads2[] = {
2984 // The origin server responds with a Type 2 message.
2985 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2986 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292987 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242988 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2989 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2990 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2991 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2992 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2993 "BtAAAAAAA=\r\n"),
2994 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362995 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242996 MockRead("You are not authorized to view this page\r\n"),
2997
2998 // Lastly we get the desired content.
2999 MockRead("HTTP/1.1 200 OK\r\n"),
3000 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3001 MockRead("Content-Length: 13\r\n\r\n"),
3002 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423003 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:243004 };
3005
[email protected]31a2bfe2010-02-09 08:03:393006 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3007 data_writes1, arraysize(data_writes1));
3008 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3009 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593010 session_deps.socket_factory.AddSocketDataProvider(&data1);
3011 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:243012
[email protected]49639fa2011-12-20 23:22:413013 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:243014
[email protected]0b0bf032010-09-21 18:08:503015 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3016
[email protected]49639fa2011-12-20 23:22:413017 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423018 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243019
3020 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423021 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243022
[email protected]0757e7702009-03-27 04:00:223023 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3024
[email protected]1c773ea12009-04-28 19:58:423025 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043026 ASSERT_FALSE(response == NULL);
3027 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:243028
[email protected]49639fa2011-12-20 23:22:413029 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:253030
[email protected]f3cf9802011-10-28 18:44:583031 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413032 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:253033 EXPECT_EQ(ERR_IO_PENDING, rv);
3034
3035 rv = callback2.WaitForResult();
3036 EXPECT_EQ(OK, rv);
3037
3038 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3039
3040 response = trans->GetResponseInfo();
3041 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:253042 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3043
[email protected]49639fa2011-12-20 23:22:413044 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:243045
[email protected]49639fa2011-12-20 23:22:413046 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423047 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243048
[email protected]0757e7702009-03-27 04:00:223049 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423050 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243051
3052 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503053 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:243054 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3055 EXPECT_EQ(13, response->headers->GetContentLength());
3056}
3057
[email protected]385a4672009-03-11 22:21:293058// Enter a wrong password, and then the correct one.
3059TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:423060 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:293061 request.method = "GET";
3062 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3063 request.load_flags = 0;
3064
[email protected]cb9bf6ca2011-01-28 13:15:273065 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3066 MockGetHostName);
3067 SessionDependencies session_deps;
3068 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3069
[email protected]385a4672009-03-11 22:21:293070 MockWrite data_writes1[] = {
3071 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3072 "Host: 172.22.68.17\r\n"
3073 "Connection: keep-alive\r\n\r\n"),
3074 };
3075
3076 MockRead data_reads1[] = {
3077 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:043078 // Negotiate and NTLM are often requested together. However, we only want
3079 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3080 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:293081 MockRead("WWW-Authenticate: NTLM\r\n"),
3082 MockRead("Connection: close\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 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423086 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293087 };
3088
3089 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:223090 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293091 // request we should be issuing -- the final header line contains a Type
3092 // 1 message.
3093 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3094 "Host: 172.22.68.17\r\n"
3095 "Connection: keep-alive\r\n"
3096 "Authorization: NTLM "
3097 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3098
3099 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3100 // (the credentials for the origin server). The second request continues
3101 // on the same connection.
3102 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3103 "Host: 172.22.68.17\r\n"
3104 "Connection: keep-alive\r\n"
3105 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3106 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3107 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
3108 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
3109 "4Ww7b7E=\r\n\r\n"),
3110 };
3111
3112 MockRead data_reads2[] = {
3113 // The origin server responds with a Type 2 message.
3114 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3115 MockRead("WWW-Authenticate: NTLM "
3116 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
3117 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3118 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3119 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3120 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3121 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3122 "BtAAAAAAA=\r\n"),
3123 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363124 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293125 MockRead("You are not authorized to view this page\r\n"),
3126
3127 // Wrong password.
3128 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:293129 MockRead("WWW-Authenticate: NTLM\r\n"),
3130 MockRead("Connection: close\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 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423134 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293135 };
3136
3137 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223138 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293139 // request we should be issuing -- the final header line contains a Type
3140 // 1 message.
3141 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3142 "Host: 172.22.68.17\r\n"
3143 "Connection: keep-alive\r\n"
3144 "Authorization: NTLM "
3145 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3146
3147 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3148 // (the credentials for the origin server). The second request continues
3149 // on the same connection.
3150 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3151 "Host: 172.22.68.17\r\n"
3152 "Connection: keep-alive\r\n"
3153 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3154 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3155 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3156 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3157 "+4MUm7c=\r\n\r\n"),
3158 };
3159
3160 MockRead data_reads3[] = {
3161 // The origin server responds with a Type 2 message.
3162 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3163 MockRead("WWW-Authenticate: NTLM "
3164 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3165 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3166 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3167 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3168 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3169 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3170 "BtAAAAAAA=\r\n"),
3171 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363172 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293173 MockRead("You are not authorized to view this page\r\n"),
3174
3175 // Lastly we get the desired content.
3176 MockRead("HTTP/1.1 200 OK\r\n"),
3177 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3178 MockRead("Content-Length: 13\r\n\r\n"),
3179 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423180 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293181 };
3182
[email protected]31a2bfe2010-02-09 08:03:393183 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3184 data_writes1, arraysize(data_writes1));
3185 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3186 data_writes2, arraysize(data_writes2));
3187 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3188 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593189 session_deps.socket_factory.AddSocketDataProvider(&data1);
3190 session_deps.socket_factory.AddSocketDataProvider(&data2);
3191 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293192
[email protected]49639fa2011-12-20 23:22:413193 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:293194
[email protected]0b0bf032010-09-21 18:08:503195 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3196
[email protected]49639fa2011-12-20 23:22:413197 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423198 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293199
3200 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423201 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293202
[email protected]0757e7702009-03-27 04:00:223203 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293204
[email protected]1c773ea12009-04-28 19:58:423205 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503206 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043207 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:293208
[email protected]49639fa2011-12-20 23:22:413209 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293210
[email protected]0757e7702009-03-27 04:00:223211 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:583212 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:413213 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423214 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293215
[email protected]10af5fe72011-01-31 16:17:253216 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423217 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293218
[email protected]0757e7702009-03-27 04:00:223219 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:413220 TestCompletionCallback callback3;
3221 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423222 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253223 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423224 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223225 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3226
3227 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043228 ASSERT_FALSE(response == NULL);
3229 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:223230
[email protected]49639fa2011-12-20 23:22:413231 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223232
3233 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:583234 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413235 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:253236 EXPECT_EQ(ERR_IO_PENDING, rv);
3237
3238 rv = callback4.WaitForResult();
3239 EXPECT_EQ(OK, rv);
3240
3241 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3242
[email protected]49639fa2011-12-20 23:22:413243 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:253244
3245 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:413246 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:423247 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223248
3249 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423250 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223251
[email protected]385a4672009-03-11 22:21:293252 response = trans->GetResponseInfo();
3253 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3254 EXPECT_EQ(13, response->headers->GetContentLength());
3255}
[email protected]ea9dc9a2009-09-05 00:43:323256#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293257
[email protected]4ddaf2502008-10-23 18:26:193258// Test reading a server response which has only headers, and no body.
3259// After some maximum number of bytes is consumed, the transaction should
3260// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3261TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423262 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193263 request.method = "GET";
3264 request.url = GURL("http://www.google.com/");
3265 request.load_flags = 0;
3266
[email protected]cb9bf6ca2011-01-28 13:15:273267 SessionDependencies session_deps;
3268 scoped_ptr<HttpTransaction> trans(
3269 new HttpNetworkTransaction(CreateSession(&session_deps)));
3270
[email protected]b75b7b2f2009-10-06 00:54:533271 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433272 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533273 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193274
3275 MockRead data_reads[] = {
3276 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433277 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193278 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423279 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193280 };
[email protected]31a2bfe2010-02-09 08:03:393281 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593282 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193283
[email protected]49639fa2011-12-20 23:22:413284 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:193285
[email protected]49639fa2011-12-20 23:22:413286 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423287 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193288
3289 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423290 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193291
[email protected]1c773ea12009-04-28 19:58:423292 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193293 EXPECT_TRUE(response == NULL);
3294}
[email protected]f4e426b2008-11-05 00:24:493295
3296// Make sure that we don't try to reuse a TCPClientSocket when failing to
3297// establish tunnel.
3298// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283299TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273300 HttpRequestInfo request;
3301 request.method = "GET";
3302 request.url = GURL("https://www.google.com/");
3303 request.load_flags = 0;
3304
[email protected]f4e426b2008-11-05 00:24:493305 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003306 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013307
[email protected]228ff742009-06-05 01:19:593308 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493309
[email protected]5695b8c2009-09-30 21:36:433310 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493311
[email protected]f4e426b2008-11-05 00:24:493312 // Since we have proxy, should try to establish tunnel.
3313 MockWrite data_writes1[] = {
3314 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453315 "Host: www.google.com\r\n"
3316 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493317 };
3318
[email protected]77848d12008-11-14 00:00:223319 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493320 // connection. Usually a proxy would return 501 (not implemented),
3321 // or 200 (tunnel established).
3322 MockRead data_reads1[] = {
3323 MockRead("HTTP/1.1 404 Not Found\r\n"),
3324 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423325 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493326 };
3327
[email protected]31a2bfe2010-02-09 08:03:393328 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3329 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593330 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493331
[email protected]49639fa2011-12-20 23:22:413332 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:493333
[email protected]49639fa2011-12-20 23:22:413334 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423335 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493336
3337 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423338 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493339
[email protected]1c773ea12009-04-28 19:58:423340 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083341 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493342
[email protected]b4404c02009-04-10 16:38:523343 // Empty the current queue. This is necessary because idle sockets are
3344 // added to the connection pool asynchronously with a PostTask.
3345 MessageLoop::current()->RunAllPending();
3346
[email protected]f4e426b2008-11-05 00:24:493347 // We now check to make sure the TCPClientSocket was not added back to
3348 // the pool.
[email protected]a42dbd142011-11-17 16:42:023349 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493350 trans.reset();
[email protected]b4404c02009-04-10 16:38:523351 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493352 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a42dbd142011-11-17 16:42:023353 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493354}
[email protected]372d34a2008-11-05 21:30:513355
[email protected]1b157c02009-04-21 01:55:403356// Make sure that we recycle a socket after reading all of the response body.
3357TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423358 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403359 request.method = "GET";
3360 request.url = GURL("http://www.google.com/");
3361 request.load_flags = 0;
3362
[email protected]cb9bf6ca2011-01-28 13:15:273363 SessionDependencies session_deps;
3364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3365
3366 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3367
[email protected]1b157c02009-04-21 01:55:403368 MockRead data_reads[] = {
3369 // A part of the response body is received with the response headers.
3370 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3371 // The rest of the response body is received in two parts.
3372 MockRead("lo"),
3373 MockRead(" world"),
3374 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423375 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403376 };
3377
[email protected]31a2bfe2010-02-09 08:03:393378 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593379 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403380
[email protected]49639fa2011-12-20 23:22:413381 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:403382
[email protected]49639fa2011-12-20 23:22:413383 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423384 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403385
3386 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423387 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403388
[email protected]1c773ea12009-04-28 19:58:423389 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503390 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:403391
3392 EXPECT_TRUE(response->headers != NULL);
3393 std::string status_line = response->headers->GetStatusLine();
3394 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3395
[email protected]a42dbd142011-11-17 16:42:023396 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403397
3398 std::string response_data;
3399 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423400 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403401 EXPECT_EQ("hello world", response_data);
3402
3403 // Empty the current queue. This is necessary because idle sockets are
3404 // added to the connection pool asynchronously with a PostTask.
3405 MessageLoop::current()->RunAllPending();
3406
3407 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023408 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403409}
3410
[email protected]76a505b2010-08-25 06:23:003411// Make sure that we recycle a SSL socket after reading all of the response
3412// body.
3413TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3414 SessionDependencies session_deps;
3415 HttpRequestInfo request;
3416 request.method = "GET";
3417 request.url = GURL("https://www.google.com/");
3418 request.load_flags = 0;
3419
3420 MockWrite data_writes[] = {
3421 MockWrite("GET / HTTP/1.1\r\n"
3422 "Host: www.google.com\r\n"
3423 "Connection: keep-alive\r\n\r\n"),
3424 };
3425
3426 MockRead data_reads[] = {
3427 MockRead("HTTP/1.1 200 OK\r\n"),
3428 MockRead("Content-Length: 11\r\n\r\n"),
3429 MockRead("hello world"),
3430 MockRead(false, OK),
3431 };
3432
3433 SSLSocketDataProvider ssl(true, OK);
3434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3435
3436 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3437 data_writes, arraysize(data_writes));
3438 session_deps.socket_factory.AddSocketDataProvider(&data);
3439
[email protected]49639fa2011-12-20 23:22:413440 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003441
3442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3443 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3444
[email protected]49639fa2011-12-20 23:22:413445 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003446
3447 EXPECT_EQ(ERR_IO_PENDING, rv);
3448 EXPECT_EQ(OK, callback.WaitForResult());
3449
3450 const HttpResponseInfo* response = trans->GetResponseInfo();
3451 ASSERT_TRUE(response != NULL);
3452 ASSERT_TRUE(response->headers != NULL);
3453 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3454
[email protected]a42dbd142011-11-17 16:42:023455 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003456
3457 std::string response_data;
3458 rv = ReadTransaction(trans.get(), &response_data);
3459 EXPECT_EQ(OK, rv);
3460 EXPECT_EQ("hello world", response_data);
3461
3462 // Empty the current queue. This is necessary because idle sockets are
3463 // added to the connection pool asynchronously with a PostTask.
3464 MessageLoop::current()->RunAllPending();
3465
3466 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023467 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003468}
3469
3470// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3471// from the pool and make sure that we recover okay.
3472TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3473 SessionDependencies session_deps;
3474 HttpRequestInfo request;
3475 request.method = "GET";
3476 request.url = GURL("https://www.google.com/");
3477 request.load_flags = 0;
3478
3479 MockWrite data_writes[] = {
3480 MockWrite("GET / HTTP/1.1\r\n"
3481 "Host: www.google.com\r\n"
3482 "Connection: keep-alive\r\n\r\n"),
3483 MockWrite("GET / HTTP/1.1\r\n"
3484 "Host: www.google.com\r\n"
3485 "Connection: keep-alive\r\n\r\n"),
3486 };
3487
3488 MockRead data_reads[] = {
3489 MockRead("HTTP/1.1 200 OK\r\n"),
3490 MockRead("Content-Length: 11\r\n\r\n"),
3491 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3492 MockRead("hello world"),
3493 MockRead(true, 0, 0) // EOF
3494 };
3495
3496 SSLSocketDataProvider ssl(true, OK);
3497 SSLSocketDataProvider ssl2(true, OK);
3498 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3499 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3500
3501 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3502 data_writes, arraysize(data_writes));
3503 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3504 data_writes, arraysize(data_writes));
3505 session_deps.socket_factory.AddSocketDataProvider(&data);
3506 session_deps.socket_factory.AddSocketDataProvider(&data2);
3507
[email protected]49639fa2011-12-20 23:22:413508 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003509
3510 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3511 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3512
[email protected]49639fa2011-12-20 23:22:413513 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003514
3515 EXPECT_EQ(ERR_IO_PENDING, rv);
3516 EXPECT_EQ(OK, callback.WaitForResult());
3517
3518 const HttpResponseInfo* response = trans->GetResponseInfo();
3519 ASSERT_TRUE(response != NULL);
3520 ASSERT_TRUE(response->headers != NULL);
3521 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3522
[email protected]a42dbd142011-11-17 16:42:023523 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003524
3525 std::string response_data;
3526 rv = ReadTransaction(trans.get(), &response_data);
3527 EXPECT_EQ(OK, rv);
3528 EXPECT_EQ("hello world", response_data);
3529
3530 // Empty the current queue. This is necessary because idle sockets are
3531 // added to the connection pool asynchronously with a PostTask.
3532 MessageLoop::current()->RunAllPending();
3533
3534 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023535 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003536
3537 // Now start the second transaction, which should reuse the previous socket.
3538
3539 trans.reset(new HttpNetworkTransaction(session));
3540
[email protected]49639fa2011-12-20 23:22:413541 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003542
3543 EXPECT_EQ(ERR_IO_PENDING, rv);
3544 EXPECT_EQ(OK, callback.WaitForResult());
3545
3546 response = trans->GetResponseInfo();
3547 ASSERT_TRUE(response != NULL);
3548 ASSERT_TRUE(response->headers != NULL);
3549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3550
[email protected]a42dbd142011-11-17 16:42:023551 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003552
3553 rv = ReadTransaction(trans.get(), &response_data);
3554 EXPECT_EQ(OK, rv);
3555 EXPECT_EQ("hello world", response_data);
3556
3557 // Empty the current queue. This is necessary because idle sockets are
3558 // added to the connection pool asynchronously with a PostTask.
3559 MessageLoop::current()->RunAllPending();
3560
3561 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023562 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003563}
3564
[email protected]b4404c02009-04-10 16:38:523565// Make sure that we recycle a socket after a zero-length response.
3566// http://crbug.com/9880
3567TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423568 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523569 request.method = "GET";
3570 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3571 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3572 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3573 "rt=prt.2642,ol.2649,xjs.2951");
3574 request.load_flags = 0;
3575
[email protected]cb9bf6ca2011-01-28 13:15:273576 SessionDependencies session_deps;
3577 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3578
3579 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3580
[email protected]b4404c02009-04-10 16:38:523581 MockRead data_reads[] = {
3582 MockRead("HTTP/1.1 204 No Content\r\n"
3583 "Content-Length: 0\r\n"
3584 "Content-Type: text/html\r\n\r\n"),
3585 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423586 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523587 };
3588
[email protected]31a2bfe2010-02-09 08:03:393589 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593590 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523591
[email protected]49639fa2011-12-20 23:22:413592 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:523593
[email protected]49639fa2011-12-20 23:22:413594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423595 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523596
3597 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423598 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523599
[email protected]1c773ea12009-04-28 19:58:423600 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503601 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:523602
3603 EXPECT_TRUE(response->headers != NULL);
3604 std::string status_line = response->headers->GetStatusLine();
3605 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3606
[email protected]a42dbd142011-11-17 16:42:023607 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523608
3609 std::string response_data;
3610 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423611 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523612 EXPECT_EQ("", response_data);
3613
3614 // Empty the current queue. This is necessary because idle sockets are
3615 // added to the connection pool asynchronously with a PostTask.
3616 MessageLoop::current()->RunAllPending();
3617
3618 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023619 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523620}
3621
[email protected]372d34a2008-11-05 21:30:513622TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423623 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513624 // Transaction 1: a GET request that succeeds. The socket is recycled
3625 // after use.
3626 request[0].method = "GET";
3627 request[0].url = GURL("http://www.google.com/");
3628 request[0].load_flags = 0;
3629 // Transaction 2: a POST request. Reuses the socket kept alive from
3630 // transaction 1. The first attempts fails when writing the POST data.
3631 // This causes the transaction to retry with a new socket. The second
3632 // attempt succeeds.
3633 request[1].method = "POST";
3634 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423635 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513636 request[1].upload_data->AppendBytes("foo", 3);
3637 request[1].load_flags = 0;
3638
[email protected]228ff742009-06-05 01:19:593639 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273640 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513641
3642 // The first socket is used for transaction 1 and the first attempt of
3643 // transaction 2.
3644
3645 // The response of transaction 1.
3646 MockRead data_reads1[] = {
3647 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3648 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423649 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513650 };
3651 // The mock write results of transaction 1 and the first attempt of
3652 // transaction 2.
3653 MockWrite data_writes1[] = {
3654 MockWrite(false, 64), // GET
3655 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423656 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513657 };
[email protected]31a2bfe2010-02-09 08:03:393658 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3659 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513660
3661 // The second socket is used for the second attempt of transaction 2.
3662
3663 // The response of transaction 2.
3664 MockRead data_reads2[] = {
3665 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3666 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423667 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513668 };
3669 // The mock write results of the second attempt of transaction 2.
3670 MockWrite data_writes2[] = {
3671 MockWrite(false, 93), // POST
3672 MockWrite(false, 3), // POST data
3673 };
[email protected]31a2bfe2010-02-09 08:03:393674 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3675 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513676
[email protected]5ecc992a42009-11-11 01:41:593677 session_deps.socket_factory.AddSocketDataProvider(&data1);
3678 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513679
3680 const char* kExpectedResponseData[] = {
3681 "hello world", "welcome"
3682 };
3683
3684 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423685 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433686 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513687
[email protected]49639fa2011-12-20 23:22:413688 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:513689
[email protected]49639fa2011-12-20 23:22:413690 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423691 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513692
3693 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423694 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513695
[email protected]1c773ea12009-04-28 19:58:423696 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503697 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:513698
3699 EXPECT_TRUE(response->headers != NULL);
3700 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3701
3702 std::string response_data;
3703 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423704 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513705 EXPECT_EQ(kExpectedResponseData[i], response_data);
3706 }
3707}
[email protected]f9ee6b52008-11-08 06:46:233708
3709// Test the request-challenge-retry sequence for basic auth when there is
3710// an identity in the URL. The request should be sent as normal, but when
[email protected]7b08ba62012-02-10 20:19:413711// it fails the identity from the URL is no longer used.
3712TEST_F(HttpNetworkTransactionTest, IgnoreAuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423713 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233714 request.method = "GET";
[email protected]a97cca42009-08-14 01:00:293715 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:413716 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:293717
[email protected]cb9bf6ca2011-01-28 13:15:273718 SessionDependencies session_deps;
3719 scoped_ptr<HttpTransaction> trans(
3720 new HttpNetworkTransaction(CreateSession(&session_deps)));
3721
[email protected]a97cca42009-08-14 01:00:293722 // The password contains an escaped character -- for this test to pass it
3723 // will need to be unescaped by HttpNetworkTransaction.
3724 EXPECT_EQ("b%40r", request.url.password());
3725
[email protected]f9ee6b52008-11-08 06:46:233726 MockWrite data_writes1[] = {
3727 MockWrite("GET / HTTP/1.1\r\n"
3728 "Host: www.google.com\r\n"
3729 "Connection: keep-alive\r\n\r\n"),
3730 };
3731
3732 MockRead data_reads1[] = {
3733 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3734 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3735 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423736 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233737 };
3738
[email protected]31a2bfe2010-02-09 08:03:393739 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3740 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593741 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233742
[email protected]49639fa2011-12-20 23:22:413743 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:413744 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423745 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233746 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423747 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223748 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3749
[email protected]ea9dc9a2009-09-05 00:43:323750 // Empty the current queue.
3751 MessageLoop::current()->RunAllPending();
3752}
3753
[email protected]f9ee6b52008-11-08 06:46:233754// Test that previously tried username/passwords for a realm get re-used.
3755TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593756 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233758
3759 // Transaction 1: authenticate (foo, bar) on MyRealm1
3760 {
[email protected]1c773ea12009-04-28 19:58:423761 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233762 request.method = "GET";
3763 request.url = GURL("http://www.google.com/x/y/z");
3764 request.load_flags = 0;
3765
[email protected]cb9bf6ca2011-01-28 13:15:273766 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3767
[email protected]f9ee6b52008-11-08 06:46:233768 MockWrite data_writes1[] = {
3769 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3770 "Host: www.google.com\r\n"
3771 "Connection: keep-alive\r\n\r\n"),
3772 };
3773
3774 MockRead data_reads1[] = {
3775 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3776 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3777 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423778 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233779 };
3780
3781 // Resend with authorization (username=foo, password=bar)
3782 MockWrite data_writes2[] = {
3783 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3784 "Host: www.google.com\r\n"
3785 "Connection: keep-alive\r\n"
3786 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3787 };
3788
3789 // Sever accepts the authorization.
3790 MockRead data_reads2[] = {
3791 MockRead("HTTP/1.0 200 OK\r\n"),
3792 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423793 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233794 };
3795
[email protected]31a2bfe2010-02-09 08:03:393796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3797 data_writes1, arraysize(data_writes1));
3798 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3799 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593800 session_deps.socket_factory.AddSocketDataProvider(&data1);
3801 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233802
[email protected]49639fa2011-12-20 23:22:413803 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233804
[email protected]49639fa2011-12-20 23:22:413805 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423806 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233807
3808 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423809 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233810
[email protected]1c773ea12009-04-28 19:58:423811 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503812 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043813 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:233814
[email protected]49639fa2011-12-20 23:22:413815 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233816
[email protected]49639fa2011-12-20 23:22:413817 rv = trans->RestartWithAuth(
3818 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423819 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233820
3821 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423822 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233823
3824 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503825 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233826 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3827 EXPECT_EQ(100, response->headers->GetContentLength());
3828 }
3829
3830 // ------------------------------------------------------------------------
3831
3832 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3833 {
[email protected]1c773ea12009-04-28 19:58:423834 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233835 request.method = "GET";
3836 // Note that Transaction 1 was at /x/y/z, so this is in the same
3837 // protection space as MyRealm1.
3838 request.url = GURL("http://www.google.com/x/y/a/b");
3839 request.load_flags = 0;
3840
[email protected]cb9bf6ca2011-01-28 13:15:273841 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3842
[email protected]f9ee6b52008-11-08 06:46:233843 MockWrite data_writes1[] = {
3844 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3845 "Host: www.google.com\r\n"
3846 "Connection: keep-alive\r\n"
3847 // Send preemptive authorization for MyRealm1
3848 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3849 };
3850
3851 // The server didn't like the preemptive authorization, and
3852 // challenges us for a different realm (MyRealm2).
3853 MockRead data_reads1[] = {
3854 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3855 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3856 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423857 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233858 };
3859
3860 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3861 MockWrite data_writes2[] = {
3862 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3863 "Host: www.google.com\r\n"
3864 "Connection: keep-alive\r\n"
3865 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3866 };
3867
3868 // Sever accepts the authorization.
3869 MockRead data_reads2[] = {
3870 MockRead("HTTP/1.0 200 OK\r\n"),
3871 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423872 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233873 };
3874
[email protected]31a2bfe2010-02-09 08:03:393875 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3876 data_writes1, arraysize(data_writes1));
3877 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3878 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593879 session_deps.socket_factory.AddSocketDataProvider(&data1);
3880 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233881
[email protected]49639fa2011-12-20 23:22:413882 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233883
[email protected]49639fa2011-12-20 23:22:413884 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233886
3887 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423888 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233889
[email protected]1c773ea12009-04-28 19:58:423890 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503891 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043892 ASSERT_TRUE(response->auth_challenge.get());
3893 EXPECT_FALSE(response->auth_challenge->is_proxy);
3894 EXPECT_EQ("www.google.com:80",
3895 response->auth_challenge->challenger.ToString());
3896 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
3897 EXPECT_EQ("basic", response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:233898
[email protected]49639fa2011-12-20 23:22:413899 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233900
[email protected]49639fa2011-12-20 23:22:413901 rv = trans->RestartWithAuth(
3902 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423903 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233904
3905 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423906 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233907
3908 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503909 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233910 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3911 EXPECT_EQ(100, response->headers->GetContentLength());
3912 }
3913
3914 // ------------------------------------------------------------------------
3915
3916 // Transaction 3: Resend a request in MyRealm's protection space --
3917 // succeed with preemptive authorization.
3918 {
[email protected]1c773ea12009-04-28 19:58:423919 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233920 request.method = "GET";
3921 request.url = GURL("http://www.google.com/x/y/z2");
3922 request.load_flags = 0;
3923
[email protected]cb9bf6ca2011-01-28 13:15:273924 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3925
[email protected]f9ee6b52008-11-08 06:46:233926 MockWrite data_writes1[] = {
3927 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3928 "Host: www.google.com\r\n"
3929 "Connection: keep-alive\r\n"
3930 // The authorization for MyRealm1 gets sent preemptively
3931 // (since the url is in the same protection space)
3932 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3933 };
3934
3935 // Sever accepts the preemptive authorization
3936 MockRead data_reads1[] = {
3937 MockRead("HTTP/1.0 200 OK\r\n"),
3938 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423939 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233940 };
3941
[email protected]31a2bfe2010-02-09 08:03:393942 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3943 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593944 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233945
[email protected]49639fa2011-12-20 23:22:413946 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233947
[email protected]49639fa2011-12-20 23:22:413948 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423949 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233950
3951 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423952 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233953
[email protected]1c773ea12009-04-28 19:58:423954 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503955 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233956
3957 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3958 EXPECT_EQ(100, response->headers->GetContentLength());
3959 }
3960
3961 // ------------------------------------------------------------------------
3962
3963 // Transaction 4: request another URL in MyRealm (however the
3964 // url is not known to belong to the protection space, so no pre-auth).
3965 {
[email protected]1c773ea12009-04-28 19:58:423966 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233967 request.method = "GET";
3968 request.url = GURL("http://www.google.com/x/1");
3969 request.load_flags = 0;
3970
[email protected]cb9bf6ca2011-01-28 13:15:273971 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3972
[email protected]f9ee6b52008-11-08 06:46:233973 MockWrite data_writes1[] = {
3974 MockWrite("GET /x/1 HTTP/1.1\r\n"
3975 "Host: www.google.com\r\n"
3976 "Connection: keep-alive\r\n\r\n"),
3977 };
3978
3979 MockRead data_reads1[] = {
3980 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3981 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3982 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423983 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233984 };
3985
3986 // Resend with authorization from MyRealm's cache.
3987 MockWrite data_writes2[] = {
3988 MockWrite("GET /x/1 HTTP/1.1\r\n"
3989 "Host: www.google.com\r\n"
3990 "Connection: keep-alive\r\n"
3991 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3992 };
3993
3994 // Sever accepts the authorization.
3995 MockRead data_reads2[] = {
3996 MockRead("HTTP/1.0 200 OK\r\n"),
3997 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423998 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233999 };
4000
[email protected]31a2bfe2010-02-09 08:03:394001 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4002 data_writes1, arraysize(data_writes1));
4003 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4004 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594005 session_deps.socket_factory.AddSocketDataProvider(&data1);
4006 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234007
[email protected]49639fa2011-12-20 23:22:414008 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234009
[email protected]49639fa2011-12-20 23:22:414010 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424011 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234012
4013 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424014 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234015
[email protected]0757e7702009-03-27 04:00:224016 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414017 TestCompletionCallback callback2;
4018 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424019 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224020 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424021 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224022 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4023
[email protected]1c773ea12009-04-28 19:58:424024 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504025 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234026 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4027 EXPECT_EQ(100, response->headers->GetContentLength());
4028 }
4029
4030 // ------------------------------------------------------------------------
4031
4032 // Transaction 5: request a URL in MyRealm, but the server rejects the
4033 // cached identity. Should invalidate and re-prompt.
4034 {
[email protected]1c773ea12009-04-28 19:58:424035 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234036 request.method = "GET";
4037 request.url = GURL("http://www.google.com/p/q/t");
4038 request.load_flags = 0;
4039
[email protected]cb9bf6ca2011-01-28 13:15:274040 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4041
[email protected]f9ee6b52008-11-08 06:46:234042 MockWrite data_writes1[] = {
4043 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4044 "Host: www.google.com\r\n"
4045 "Connection: keep-alive\r\n\r\n"),
4046 };
4047
4048 MockRead data_reads1[] = {
4049 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4050 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4051 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424052 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234053 };
4054
4055 // Resend with authorization from cache for MyRealm.
4056 MockWrite data_writes2[] = {
4057 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4058 "Host: www.google.com\r\n"
4059 "Connection: keep-alive\r\n"
4060 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4061 };
4062
4063 // Sever rejects the authorization.
4064 MockRead data_reads2[] = {
4065 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4066 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4067 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424068 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234069 };
4070
4071 // At this point we should prompt for new credentials for MyRealm.
4072 // Restart with username=foo3, password=foo4.
4073 MockWrite data_writes3[] = {
4074 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4075 "Host: www.google.com\r\n"
4076 "Connection: keep-alive\r\n"
4077 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4078 };
4079
4080 // Sever accepts the authorization.
4081 MockRead data_reads3[] = {
4082 MockRead("HTTP/1.0 200 OK\r\n"),
4083 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424084 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234085 };
4086
[email protected]31a2bfe2010-02-09 08:03:394087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4088 data_writes1, arraysize(data_writes1));
4089 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4090 data_writes2, arraysize(data_writes2));
4091 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4092 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594093 session_deps.socket_factory.AddSocketDataProvider(&data1);
4094 session_deps.socket_factory.AddSocketDataProvider(&data2);
4095 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234096
[email protected]49639fa2011-12-20 23:22:414097 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234098
[email protected]49639fa2011-12-20 23:22:414099 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424100 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234101
4102 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424103 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234104
[email protected]0757e7702009-03-27 04:00:224105 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414106 TestCompletionCallback callback2;
4107 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224109 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424110 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224111 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4112
[email protected]1c773ea12009-04-28 19:58:424113 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504114 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044115 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:234116
[email protected]49639fa2011-12-20 23:22:414117 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234118
[email protected]49639fa2011-12-20 23:22:414119 rv = trans->RestartWithAuth(
4120 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:424121 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234122
[email protected]0757e7702009-03-27 04:00:224123 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424124 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234125
4126 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504127 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234128 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4129 EXPECT_EQ(100, response->headers->GetContentLength());
4130 }
4131}
[email protected]89ceba9a2009-03-21 03:46:064132
[email protected]3c32c5f2010-05-18 15:18:124133// Tests that nonce count increments when multiple auth attempts
4134// are started with the same nonce.
4135TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4136 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444137 HttpAuthHandlerDigest::Factory* digest_factory =
4138 new HttpAuthHandlerDigest::Factory();
4139 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4140 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4141 digest_factory->set_nonce_generator(nonce_generator);
4142 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274143 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124144
4145 // Transaction 1: authenticate (foo, bar) on MyRealm1
4146 {
[email protected]3c32c5f2010-05-18 15:18:124147 HttpRequestInfo request;
4148 request.method = "GET";
4149 request.url = GURL("http://www.google.com/x/y/z");
4150 request.load_flags = 0;
4151
[email protected]cb9bf6ca2011-01-28 13:15:274152 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4153
[email protected]3c32c5f2010-05-18 15:18:124154 MockWrite data_writes1[] = {
4155 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4156 "Host: www.google.com\r\n"
4157 "Connection: keep-alive\r\n\r\n"),
4158 };
4159
4160 MockRead data_reads1[] = {
4161 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4162 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4163 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4164 MockRead(false, OK),
4165 };
4166
4167 // Resend with authorization (username=foo, password=bar)
4168 MockWrite data_writes2[] = {
4169 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4170 "Host: www.google.com\r\n"
4171 "Connection: keep-alive\r\n"
4172 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4173 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4174 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4175 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4176 };
4177
4178 // Sever accepts the authorization.
4179 MockRead data_reads2[] = {
4180 MockRead("HTTP/1.0 200 OK\r\n"),
4181 MockRead(false, OK),
4182 };
4183
4184 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4185 data_writes1, arraysize(data_writes1));
4186 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4187 data_writes2, arraysize(data_writes2));
4188 session_deps.socket_factory.AddSocketDataProvider(&data1);
4189 session_deps.socket_factory.AddSocketDataProvider(&data2);
4190
[email protected]49639fa2011-12-20 23:22:414191 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124192
[email protected]49639fa2011-12-20 23:22:414193 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124194 EXPECT_EQ(ERR_IO_PENDING, rv);
4195
4196 rv = callback1.WaitForResult();
4197 EXPECT_EQ(OK, rv);
4198
4199 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504200 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044201 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:124202
[email protected]49639fa2011-12-20 23:22:414203 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:124204
[email protected]49639fa2011-12-20 23:22:414205 rv = trans->RestartWithAuth(
4206 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:124207 EXPECT_EQ(ERR_IO_PENDING, rv);
4208
4209 rv = callback2.WaitForResult();
4210 EXPECT_EQ(OK, rv);
4211
4212 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504213 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4215 }
4216
4217 // ------------------------------------------------------------------------
4218
4219 // Transaction 2: Request another resource in digestive's protection space.
4220 // This will preemptively add an Authorization header which should have an
4221 // "nc" value of 2 (as compared to 1 in the first use.
4222 {
[email protected]3c32c5f2010-05-18 15:18:124223 HttpRequestInfo request;
4224 request.method = "GET";
4225 // Note that Transaction 1 was at /x/y/z, so this is in the same
4226 // protection space as digest.
4227 request.url = GURL("http://www.google.com/x/y/a/b");
4228 request.load_flags = 0;
4229
[email protected]cb9bf6ca2011-01-28 13:15:274230 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4231
[email protected]3c32c5f2010-05-18 15:18:124232 MockWrite data_writes1[] = {
4233 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4234 "Host: www.google.com\r\n"
4235 "Connection: keep-alive\r\n"
4236 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4237 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4238 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4239 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4240 };
4241
4242 // Sever accepts the authorization.
4243 MockRead data_reads1[] = {
4244 MockRead("HTTP/1.0 200 OK\r\n"),
4245 MockRead("Content-Length: 100\r\n\r\n"),
4246 MockRead(false, OK),
4247 };
4248
4249 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4250 data_writes1, arraysize(data_writes1));
4251 session_deps.socket_factory.AddSocketDataProvider(&data1);
4252
[email protected]49639fa2011-12-20 23:22:414253 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124254
[email protected]49639fa2011-12-20 23:22:414255 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124256 EXPECT_EQ(ERR_IO_PENDING, rv);
4257
4258 rv = callback1.WaitForResult();
4259 EXPECT_EQ(OK, rv);
4260
4261 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504262 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124263 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4264 }
4265}
4266
[email protected]89ceba9a2009-03-21 03:46:064267// Test the ResetStateForRestart() private method.
4268TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4269 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594270 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404271 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434272 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064273
4274 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064275 trans->read_buf_ = new IOBuffer(15);
4276 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204277 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064278
4279 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144280 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574281 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:084282 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:574283 response->response_time = base::Time::Now();
4284 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064285
4286 { // Setup state for response_.vary_data
4287 HttpRequestInfo request;
4288 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4289 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274290 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434291 request.extra_headers.SetHeader("Foo", "1");
4292 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574293 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064294 }
4295
4296 // Cause the above state to be reset.
4297 trans->ResetStateForRestart();
4298
4299 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074300 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064301 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204302 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574303 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4304 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044305 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:084306 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:574307 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064308}
4309
[email protected]bacff652009-03-31 17:50:334310// Test HTTPS connections to a site with a bad certificate
4311TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334312 HttpRequestInfo request;
4313 request.method = "GET";
4314 request.url = GURL("https://www.google.com/");
4315 request.load_flags = 0;
4316
[email protected]cb9bf6ca2011-01-28 13:15:274317 SessionDependencies session_deps;
4318 scoped_ptr<HttpTransaction> trans(
4319 new HttpNetworkTransaction(CreateSession(&session_deps)));
4320
[email protected]bacff652009-03-31 17:50:334321 MockWrite data_writes[] = {
4322 MockWrite("GET / HTTP/1.1\r\n"
4323 "Host: www.google.com\r\n"
4324 "Connection: keep-alive\r\n\r\n"),
4325 };
4326
4327 MockRead data_reads[] = {
4328 MockRead("HTTP/1.0 200 OK\r\n"),
4329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4330 MockRead("Content-Length: 100\r\n\r\n"),
4331 MockRead(false, OK),
4332 };
4333
[email protected]5ecc992a42009-11-11 01:41:594334 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394335 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4336 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594337 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4338 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334339
[email protected]5ecc992a42009-11-11 01:41:594340 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4341 session_deps.socket_factory.AddSocketDataProvider(&data);
4342 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334344
[email protected]49639fa2011-12-20 23:22:414345 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334346
[email protected]49639fa2011-12-20 23:22:414347 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334348 EXPECT_EQ(ERR_IO_PENDING, rv);
4349
4350 rv = callback.WaitForResult();
4351 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4352
[email protected]49639fa2011-12-20 23:22:414353 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334354 EXPECT_EQ(ERR_IO_PENDING, rv);
4355
4356 rv = callback.WaitForResult();
4357 EXPECT_EQ(OK, rv);
4358
4359 const HttpResponseInfo* response = trans->GetResponseInfo();
4360
[email protected]fe2255a2011-09-20 19:37:504361 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334362 EXPECT_EQ(100, response->headers->GetContentLength());
4363}
4364
4365// Test HTTPS connections to a site with a bad certificate, going through a
4366// proxy
4367TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004368 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334369
4370 HttpRequestInfo request;
4371 request.method = "GET";
4372 request.url = GURL("https://www.google.com/");
4373 request.load_flags = 0;
4374
4375 MockWrite proxy_writes[] = {
4376 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454377 "Host: www.google.com\r\n"
4378 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334379 };
4380
4381 MockRead proxy_reads[] = {
4382 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424383 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334384 };
4385
4386 MockWrite data_writes[] = {
4387 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454388 "Host: www.google.com\r\n"
4389 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334390 MockWrite("GET / HTTP/1.1\r\n"
4391 "Host: www.google.com\r\n"
4392 "Connection: keep-alive\r\n\r\n"),
4393 };
4394
4395 MockRead data_reads[] = {
4396 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4397 MockRead("HTTP/1.0 200 OK\r\n"),
4398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4399 MockRead("Content-Length: 100\r\n\r\n"),
4400 MockRead(false, OK),
4401 };
4402
[email protected]31a2bfe2010-02-09 08:03:394403 StaticSocketDataProvider ssl_bad_certificate(
4404 proxy_reads, arraysize(proxy_reads),
4405 proxy_writes, arraysize(proxy_writes));
4406 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4407 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594408 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4409 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334410
[email protected]5ecc992a42009-11-11 01:41:594411 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4412 session_deps.socket_factory.AddSocketDataProvider(&data);
4413 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4414 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334415
[email protected]49639fa2011-12-20 23:22:414416 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334417
4418 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594419 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334420
[email protected]d207a5f2009-06-04 05:28:404421 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434422 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334423
[email protected]49639fa2011-12-20 23:22:414424 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334425 EXPECT_EQ(ERR_IO_PENDING, rv);
4426
4427 rv = callback.WaitForResult();
4428 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4429
[email protected]49639fa2011-12-20 23:22:414430 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334431 EXPECT_EQ(ERR_IO_PENDING, rv);
4432
4433 rv = callback.WaitForResult();
4434 EXPECT_EQ(OK, rv);
4435
4436 const HttpResponseInfo* response = trans->GetResponseInfo();
4437
[email protected]fe2255a2011-09-20 19:37:504438 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334439 EXPECT_EQ(100, response->headers->GetContentLength());
4440 }
4441}
4442
[email protected]2df19bb2010-08-25 20:13:464443
4444// Test HTTPS connections to a site, going through an HTTPS proxy
4445TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114446 SessionDependencies session_deps(ProxyService::CreateFixed(
4447 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464448
4449 HttpRequestInfo request;
4450 request.method = "GET";
4451 request.url = GURL("https://www.google.com/");
4452 request.load_flags = 0;
4453
4454 MockWrite data_writes[] = {
4455 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4456 "Host: www.google.com\r\n"
4457 "Proxy-Connection: keep-alive\r\n\r\n"),
4458 MockWrite("GET / HTTP/1.1\r\n"
4459 "Host: www.google.com\r\n"
4460 "Connection: keep-alive\r\n\r\n"),
4461 };
4462
4463 MockRead data_reads[] = {
4464 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4465 MockRead("HTTP/1.1 200 OK\r\n"),
4466 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4467 MockRead("Content-Length: 100\r\n\r\n"),
4468 MockRead(false, OK),
4469 };
4470
4471 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4472 data_writes, arraysize(data_writes));
4473 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4474 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4475
4476 session_deps.socket_factory.AddSocketDataProvider(&data);
4477 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4478 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4479
[email protected]49639fa2011-12-20 23:22:414480 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464481
4482 scoped_ptr<HttpTransaction> trans(
4483 new HttpNetworkTransaction(CreateSession(&session_deps)));
4484
[email protected]49639fa2011-12-20 23:22:414485 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464486 EXPECT_EQ(ERR_IO_PENDING, rv);
4487
4488 rv = callback.WaitForResult();
4489 EXPECT_EQ(OK, rv);
4490 const HttpResponseInfo* response = trans->GetResponseInfo();
4491
[email protected]fe2255a2011-09-20 19:37:504492 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464493
4494 EXPECT_TRUE(response->headers->IsKeepAlive());
4495 EXPECT_EQ(200, response->headers->response_code());
4496 EXPECT_EQ(100, response->headers->GetContentLength());
4497 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4498}
4499
[email protected]511f6f52010-12-17 03:58:294500// Test an HTTPS Proxy's ability to redirect a CONNECT request
4501TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4502 SessionDependencies session_deps(
4503 ProxyService::CreateFixed("https://proxy:70"));
4504
4505 HttpRequestInfo request;
4506 request.method = "GET";
4507 request.url = GURL("https://www.google.com/");
4508 request.load_flags = 0;
4509
4510 MockWrite data_writes[] = {
4511 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4512 "Host: www.google.com\r\n"
4513 "Proxy-Connection: keep-alive\r\n\r\n"),
4514 };
4515
4516 MockRead data_reads[] = {
4517 MockRead("HTTP/1.1 302 Redirect\r\n"),
4518 MockRead("Location: http://login.example.com/\r\n"),
4519 MockRead("Content-Length: 0\r\n\r\n"),
4520 MockRead(false, OK),
4521 };
4522
4523 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4524 data_writes, arraysize(data_writes));
4525 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4526
4527 session_deps.socket_factory.AddSocketDataProvider(&data);
4528 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4529
[email protected]49639fa2011-12-20 23:22:414530 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294531
4532 scoped_ptr<HttpTransaction> trans(
4533 new HttpNetworkTransaction(CreateSession(&session_deps)));
4534
[email protected]49639fa2011-12-20 23:22:414535 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294536 EXPECT_EQ(ERR_IO_PENDING, rv);
4537
4538 rv = callback.WaitForResult();
4539 EXPECT_EQ(OK, rv);
4540 const HttpResponseInfo* response = trans->GetResponseInfo();
4541
[email protected]fe2255a2011-09-20 19:37:504542 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294543
4544 EXPECT_EQ(302, response->headers->response_code());
4545 std::string url;
4546 EXPECT_TRUE(response->headers->IsRedirect(&url));
4547 EXPECT_EQ("http://login.example.com/", url);
4548}
4549
4550// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4551TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4552 SessionDependencies session_deps(
4553 ProxyService::CreateFixed("https://proxy:70"));
4554
4555 HttpRequestInfo request;
4556 request.method = "GET";
4557 request.url = GURL("https://www.google.com/");
4558 request.load_flags = 0;
4559
4560 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4561 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4562 MockWrite data_writes[] = {
4563 CreateMockWrite(*conn.get(), 0, false),
4564 };
4565
4566 static const char* const kExtraHeaders[] = {
4567 "location",
4568 "http://login.example.com/",
4569 };
4570 scoped_ptr<spdy::SpdyFrame> resp(
4571 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4572 arraysize(kExtraHeaders)/2, 1));
4573 MockRead data_reads[] = {
4574 CreateMockRead(*resp.get(), 1, false),
4575 MockRead(true, 0, 2), // EOF
4576 };
4577
[email protected]a1595312012-01-22 03:25:044578 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294579 new DelayedSocketData(
4580 1, // wait for one write to finish before reading.
4581 data_reads, arraysize(data_reads),
4582 data_writes, arraysize(data_writes)));
4583 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
[email protected]e58c1b82012-02-22 23:07:514584 proxy_ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]511f6f52010-12-17 03:58:294585
4586 session_deps.socket_factory.AddSocketDataProvider(data.get());
4587 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4588
[email protected]49639fa2011-12-20 23:22:414589 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294590
4591 scoped_ptr<HttpTransaction> trans(
4592 new HttpNetworkTransaction(CreateSession(&session_deps)));
4593
[email protected]49639fa2011-12-20 23:22:414594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294595 EXPECT_EQ(ERR_IO_PENDING, rv);
4596
4597 rv = callback.WaitForResult();
4598 EXPECT_EQ(OK, rv);
4599 const HttpResponseInfo* response = trans->GetResponseInfo();
4600
[email protected]fe2255a2011-09-20 19:37:504601 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294602
4603 EXPECT_EQ(302, response->headers->response_code());
4604 std::string url;
4605 EXPECT_TRUE(response->headers->IsRedirect(&url));
4606 EXPECT_EQ("http://login.example.com/", url);
4607}
4608
4609// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4610TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4611 SessionDependencies session_deps(
4612 ProxyService::CreateFixed("https://proxy:70"));
4613
4614 HttpRequestInfo request;
4615 request.method = "GET";
4616 request.url = GURL("https://www.google.com/");
4617 request.load_flags = 0;
4618
4619 MockWrite data_writes[] = {
4620 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4621 "Host: www.google.com\r\n"
4622 "Proxy-Connection: keep-alive\r\n\r\n"),
4623 };
4624
4625 MockRead data_reads[] = {
4626 MockRead("HTTP/1.1 404 Not Found\r\n"),
4627 MockRead("Content-Length: 23\r\n\r\n"),
4628 MockRead("The host does not exist"),
4629 MockRead(false, OK),
4630 };
4631
4632 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4633 data_writes, arraysize(data_writes));
4634 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4635
4636 session_deps.socket_factory.AddSocketDataProvider(&data);
4637 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4638
[email protected]49639fa2011-12-20 23:22:414639 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294640
4641 scoped_ptr<HttpTransaction> trans(
4642 new HttpNetworkTransaction(CreateSession(&session_deps)));
4643
[email protected]49639fa2011-12-20 23:22:414644 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294645 EXPECT_EQ(ERR_IO_PENDING, rv);
4646
4647 rv = callback.WaitForResult();
4648 EXPECT_EQ(OK, rv);
4649 const HttpResponseInfo* response = trans->GetResponseInfo();
4650
[email protected]fe2255a2011-09-20 19:37:504651 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294652
4653 EXPECT_EQ(404, response->headers->response_code());
4654 EXPECT_EQ(23, response->headers->GetContentLength());
4655 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4656 EXPECT_FALSE(response->ssl_info.is_valid());
4657
4658 std::string response_data;
4659 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4660 EXPECT_EQ("The host does not exist", response_data);
4661}
4662
4663// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4664// request
4665TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4666 SessionDependencies session_deps(
4667 ProxyService::CreateFixed("https://proxy:70"));
4668
4669 HttpRequestInfo request;
4670 request.method = "GET";
4671 request.url = GURL("https://www.google.com/");
4672 request.load_flags = 0;
4673
4674 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4675 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4676 MockWrite data_writes[] = {
4677 CreateMockWrite(*conn.get(), 0, false),
4678 };
4679
4680 static const char* const kExtraHeaders[] = {
4681 "location",
4682 "http://login.example.com/",
4683 };
4684 scoped_ptr<spdy::SpdyFrame> resp(
4685 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4686 arraysize(kExtraHeaders)/2, 1));
4687 scoped_ptr<spdy::SpdyFrame> body(
4688 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4689 MockRead data_reads[] = {
4690 CreateMockRead(*resp.get(), 1, false),
4691 CreateMockRead(*body.get(), 2, false),
4692 MockRead(true, 0, 3), // EOF
4693 };
4694
[email protected]a1595312012-01-22 03:25:044695 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294696 new DelayedSocketData(
4697 1, // wait for one write to finish before reading.
4698 data_reads, arraysize(data_reads),
4699 data_writes, arraysize(data_writes)));
4700 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
[email protected]e58c1b82012-02-22 23:07:514701 proxy_ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]511f6f52010-12-17 03:58:294702
4703 session_deps.socket_factory.AddSocketDataProvider(data.get());
4704 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4705
[email protected]49639fa2011-12-20 23:22:414706 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294707
4708 scoped_ptr<HttpTransaction> trans(
4709 new HttpNetworkTransaction(CreateSession(&session_deps)));
4710
[email protected]49639fa2011-12-20 23:22:414711 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294712 EXPECT_EQ(ERR_IO_PENDING, rv);
4713
4714 rv = callback.WaitForResult();
4715 EXPECT_EQ(OK, rv);
4716 const HttpResponseInfo* response = trans->GetResponseInfo();
4717
[email protected]fe2255a2011-09-20 19:37:504718 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294719
4720 EXPECT_EQ(404, response->headers->response_code());
4721 EXPECT_FALSE(response->ssl_info.is_valid());
4722
4723 std::string response_data;
4724 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4725 EXPECT_EQ("The host does not exist", response_data);
4726}
4727
[email protected]2df19bb2010-08-25 20:13:464728// Test HTTPS connections to a site with a bad certificate, going through an
4729// HTTPS proxy
4730TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114731 SessionDependencies session_deps(ProxyService::CreateFixed(
4732 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464733
4734 HttpRequestInfo request;
4735 request.method = "GET";
4736 request.url = GURL("https://www.google.com/");
4737 request.load_flags = 0;
4738
4739 // Attempt to fetch the URL from a server with a bad cert
4740 MockWrite bad_cert_writes[] = {
4741 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4742 "Host: www.google.com\r\n"
4743 "Proxy-Connection: keep-alive\r\n\r\n"),
4744 };
4745
4746 MockRead bad_cert_reads[] = {
4747 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4748 MockRead(false, OK)
4749 };
4750
4751 // Attempt to fetch the URL with a good cert
4752 MockWrite good_data_writes[] = {
4753 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4754 "Host: www.google.com\r\n"
4755 "Proxy-Connection: keep-alive\r\n\r\n"),
4756 MockWrite("GET / HTTP/1.1\r\n"
4757 "Host: www.google.com\r\n"
4758 "Connection: keep-alive\r\n\r\n"),
4759 };
4760
4761 MockRead good_cert_reads[] = {
4762 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4763 MockRead("HTTP/1.0 200 OK\r\n"),
4764 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4765 MockRead("Content-Length: 100\r\n\r\n"),
4766 MockRead(false, OK),
4767 };
4768
4769 StaticSocketDataProvider ssl_bad_certificate(
4770 bad_cert_reads, arraysize(bad_cert_reads),
4771 bad_cert_writes, arraysize(bad_cert_writes));
4772 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4773 good_data_writes, arraysize(good_data_writes));
4774 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4775 SSLSocketDataProvider ssl(true, OK);
4776
4777 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4778 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4779 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4780 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4781
4782 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4783 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4784 session_deps.socket_factory.AddSocketDataProvider(&data);
4785 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4786
[email protected]49639fa2011-12-20 23:22:414787 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464788
4789 scoped_ptr<HttpTransaction> trans(
4790 new HttpNetworkTransaction(CreateSession(&session_deps)));
4791
[email protected]49639fa2011-12-20 23:22:414792 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464793 EXPECT_EQ(ERR_IO_PENDING, rv);
4794
4795 rv = callback.WaitForResult();
4796 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4797
[email protected]49639fa2011-12-20 23:22:414798 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:464799 EXPECT_EQ(ERR_IO_PENDING, rv);
4800
4801 rv = callback.WaitForResult();
4802 EXPECT_EQ(OK, rv);
4803
4804 const HttpResponseInfo* response = trans->GetResponseInfo();
4805
[email protected]fe2255a2011-09-20 19:37:504806 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464807 EXPECT_EQ(100, response->headers->GetContentLength());
4808}
4809
[email protected]1c773ea12009-04-28 19:58:424810TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424811 HttpRequestInfo request;
4812 request.method = "GET";
4813 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434814 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4815 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424816
[email protected]cb9bf6ca2011-01-28 13:15:274817 SessionDependencies session_deps;
4818 scoped_ptr<HttpTransaction> trans(
4819 new HttpNetworkTransaction(CreateSession(&session_deps)));
4820
[email protected]1c773ea12009-04-28 19:58:424821 MockWrite data_writes[] = {
4822 MockWrite("GET / HTTP/1.1\r\n"
4823 "Host: www.google.com\r\n"
4824 "Connection: keep-alive\r\n"
4825 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4826 };
4827
4828 // Lastly, the server responds with the actual content.
4829 MockRead data_reads[] = {
4830 MockRead("HTTP/1.0 200 OK\r\n"),
4831 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4832 MockRead("Content-Length: 100\r\n\r\n"),
4833 MockRead(false, OK),
4834 };
4835
[email protected]31a2bfe2010-02-09 08:03:394836 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4837 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594838 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424839
[email protected]49639fa2011-12-20 23:22:414840 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424841
[email protected]49639fa2011-12-20 23:22:414842 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424843 EXPECT_EQ(ERR_IO_PENDING, rv);
4844
4845 rv = callback.WaitForResult();
4846 EXPECT_EQ(OK, rv);
4847}
4848
[email protected]da81f132010-08-18 23:39:294849TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294850 HttpRequestInfo request;
4851 request.method = "GET";
4852 request.url = GURL("https://www.google.com/");
4853 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4854 "Chromium Ultra Awesome X Edition");
4855
[email protected]cb9bf6ca2011-01-28 13:15:274856 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4857 scoped_ptr<HttpTransaction> trans(
4858 new HttpNetworkTransaction(CreateSession(&session_deps)));
4859
[email protected]da81f132010-08-18 23:39:294860 MockWrite data_writes[] = {
4861 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4862 "Host: www.google.com\r\n"
4863 "Proxy-Connection: keep-alive\r\n"
4864 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4865 };
4866 MockRead data_reads[] = {
4867 // Return an error, so the transaction stops here (this test isn't
4868 // interested in the rest).
4869 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4870 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4871 MockRead("Proxy-Connection: close\r\n\r\n"),
4872 };
4873
4874 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4875 data_writes, arraysize(data_writes));
4876 session_deps.socket_factory.AddSocketDataProvider(&data);
4877
[email protected]49639fa2011-12-20 23:22:414878 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:294879
[email protected]49639fa2011-12-20 23:22:414880 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:294881 EXPECT_EQ(ERR_IO_PENDING, rv);
4882
4883 rv = callback.WaitForResult();
4884 EXPECT_EQ(OK, rv);
4885}
4886
[email protected]1c773ea12009-04-28 19:58:424887TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424888 HttpRequestInfo request;
4889 request.method = "GET";
4890 request.url = GURL("http://www.google.com/");
4891 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:164892 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
4893 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:424894
[email protected]cb9bf6ca2011-01-28 13:15:274895 SessionDependencies session_deps;
4896 scoped_ptr<HttpTransaction> trans(
4897 new HttpNetworkTransaction(CreateSession(&session_deps)));
4898
[email protected]1c773ea12009-04-28 19:58:424899 MockWrite data_writes[] = {
4900 MockWrite("GET / HTTP/1.1\r\n"
4901 "Host: www.google.com\r\n"
4902 "Connection: keep-alive\r\n"
4903 "Referer: http://the.previous.site.com/\r\n\r\n"),
4904 };
4905
4906 // Lastly, the server responds with the actual content.
4907 MockRead data_reads[] = {
4908 MockRead("HTTP/1.0 200 OK\r\n"),
4909 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4910 MockRead("Content-Length: 100\r\n\r\n"),
4911 MockRead(false, OK),
4912 };
4913
[email protected]31a2bfe2010-02-09 08:03:394914 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4915 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594916 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424917
[email protected]49639fa2011-12-20 23:22:414918 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424919
[email protected]49639fa2011-12-20 23:22:414920 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424921 EXPECT_EQ(ERR_IO_PENDING, rv);
4922
4923 rv = callback.WaitForResult();
4924 EXPECT_EQ(OK, rv);
4925}
4926
4927TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424928 HttpRequestInfo request;
4929 request.method = "POST";
4930 request.url = GURL("http://www.google.com/");
4931
[email protected]cb9bf6ca2011-01-28 13:15:274932 SessionDependencies session_deps;
4933 scoped_ptr<HttpTransaction> trans(
4934 new HttpNetworkTransaction(CreateSession(&session_deps)));
4935
[email protected]1c773ea12009-04-28 19:58:424936 MockWrite data_writes[] = {
4937 MockWrite("POST / HTTP/1.1\r\n"
4938 "Host: www.google.com\r\n"
4939 "Connection: keep-alive\r\n"
4940 "Content-Length: 0\r\n\r\n"),
4941 };
4942
4943 // Lastly, the server responds with the actual content.
4944 MockRead data_reads[] = {
4945 MockRead("HTTP/1.0 200 OK\r\n"),
4946 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4947 MockRead("Content-Length: 100\r\n\r\n"),
4948 MockRead(false, OK),
4949 };
4950
[email protected]31a2bfe2010-02-09 08:03:394951 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4952 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594953 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424954
[email protected]49639fa2011-12-20 23:22:414955 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424956
[email protected]49639fa2011-12-20 23:22:414957 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424958 EXPECT_EQ(ERR_IO_PENDING, rv);
4959
4960 rv = callback.WaitForResult();
4961 EXPECT_EQ(OK, rv);
4962}
4963
4964TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424965 HttpRequestInfo request;
4966 request.method = "PUT";
4967 request.url = GURL("http://www.google.com/");
4968
[email protected]cb9bf6ca2011-01-28 13:15:274969 SessionDependencies session_deps;
4970 scoped_ptr<HttpTransaction> trans(
4971 new HttpNetworkTransaction(CreateSession(&session_deps)));
4972
[email protected]1c773ea12009-04-28 19:58:424973 MockWrite data_writes[] = {
4974 MockWrite("PUT / HTTP/1.1\r\n"
4975 "Host: www.google.com\r\n"
4976 "Connection: keep-alive\r\n"
4977 "Content-Length: 0\r\n\r\n"),
4978 };
4979
4980 // Lastly, the server responds with the actual content.
4981 MockRead data_reads[] = {
4982 MockRead("HTTP/1.0 200 OK\r\n"),
4983 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4984 MockRead("Content-Length: 100\r\n\r\n"),
4985 MockRead(false, OK),
4986 };
4987
[email protected]31a2bfe2010-02-09 08:03:394988 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4989 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594990 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424991
[email protected]49639fa2011-12-20 23:22:414992 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424993
[email protected]49639fa2011-12-20 23:22:414994 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424995 EXPECT_EQ(ERR_IO_PENDING, rv);
4996
4997 rv = callback.WaitForResult();
4998 EXPECT_EQ(OK, rv);
4999}
5000
5001TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425002 HttpRequestInfo request;
5003 request.method = "HEAD";
5004 request.url = GURL("http://www.google.com/");
5005
[email protected]cb9bf6ca2011-01-28 13:15:275006 SessionDependencies session_deps;
5007 scoped_ptr<HttpTransaction> trans(
5008 new HttpNetworkTransaction(CreateSession(&session_deps)));
5009
[email protected]1c773ea12009-04-28 19:58:425010 MockWrite data_writes[] = {
5011 MockWrite("HEAD / HTTP/1.1\r\n"
5012 "Host: www.google.com\r\n"
5013 "Connection: keep-alive\r\n"
5014 "Content-Length: 0\r\n\r\n"),
5015 };
5016
5017 // Lastly, the server responds with the actual content.
5018 MockRead data_reads[] = {
5019 MockRead("HTTP/1.0 200 OK\r\n"),
5020 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5021 MockRead("Content-Length: 100\r\n\r\n"),
5022 MockRead(false, OK),
5023 };
5024
[email protected]31a2bfe2010-02-09 08:03:395025 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5026 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595027 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425028
[email protected]49639fa2011-12-20 23:22:415029 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425030
[email protected]49639fa2011-12-20 23:22:415031 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425032 EXPECT_EQ(ERR_IO_PENDING, rv);
5033
5034 rv = callback.WaitForResult();
5035 EXPECT_EQ(OK, rv);
5036}
5037
5038TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425039 HttpRequestInfo request;
5040 request.method = "GET";
5041 request.url = GURL("http://www.google.com/");
5042 request.load_flags = LOAD_BYPASS_CACHE;
5043
[email protected]cb9bf6ca2011-01-28 13:15:275044 SessionDependencies session_deps;
5045 scoped_ptr<HttpTransaction> trans(
5046 new HttpNetworkTransaction(CreateSession(&session_deps)));
5047
[email protected]1c773ea12009-04-28 19:58:425048 MockWrite data_writes[] = {
5049 MockWrite("GET / HTTP/1.1\r\n"
5050 "Host: www.google.com\r\n"
5051 "Connection: keep-alive\r\n"
5052 "Pragma: no-cache\r\n"
5053 "Cache-Control: no-cache\r\n\r\n"),
5054 };
5055
5056 // Lastly, the server responds with the actual content.
5057 MockRead data_reads[] = {
5058 MockRead("HTTP/1.0 200 OK\r\n"),
5059 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5060 MockRead("Content-Length: 100\r\n\r\n"),
5061 MockRead(false, OK),
5062 };
5063
[email protected]31a2bfe2010-02-09 08:03:395064 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5065 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595066 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425067
[email protected]49639fa2011-12-20 23:22:415068 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425069
[email protected]49639fa2011-12-20 23:22:415070 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425071 EXPECT_EQ(ERR_IO_PENDING, rv);
5072
5073 rv = callback.WaitForResult();
5074 EXPECT_EQ(OK, rv);
5075}
5076
5077TEST_F(HttpNetworkTransactionTest,
5078 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425079 HttpRequestInfo request;
5080 request.method = "GET";
5081 request.url = GURL("http://www.google.com/");
5082 request.load_flags = LOAD_VALIDATE_CACHE;
5083
[email protected]cb9bf6ca2011-01-28 13:15:275084 SessionDependencies session_deps;
5085 scoped_ptr<HttpTransaction> trans(
5086 new HttpNetworkTransaction(CreateSession(&session_deps)));
5087
[email protected]1c773ea12009-04-28 19:58:425088 MockWrite data_writes[] = {
5089 MockWrite("GET / HTTP/1.1\r\n"
5090 "Host: www.google.com\r\n"
5091 "Connection: keep-alive\r\n"
5092 "Cache-Control: max-age=0\r\n\r\n"),
5093 };
5094
5095 // Lastly, the server responds with the actual content.
5096 MockRead data_reads[] = {
5097 MockRead("HTTP/1.0 200 OK\r\n"),
5098 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5099 MockRead("Content-Length: 100\r\n\r\n"),
5100 MockRead(false, OK),
5101 };
5102
[email protected]31a2bfe2010-02-09 08:03:395103 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5104 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595105 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425106
[email protected]49639fa2011-12-20 23:22:415107 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425108
[email protected]49639fa2011-12-20 23:22:415109 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425110 EXPECT_EQ(ERR_IO_PENDING, rv);
5111
5112 rv = callback.WaitForResult();
5113 EXPECT_EQ(OK, rv);
5114}
5115
5116TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425117 HttpRequestInfo request;
5118 request.method = "GET";
5119 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435120 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425121
[email protected]cb9bf6ca2011-01-28 13:15:275122 SessionDependencies session_deps;
5123 scoped_ptr<HttpTransaction> trans(
5124 new HttpNetworkTransaction(CreateSession(&session_deps)));
5125
[email protected]1c773ea12009-04-28 19:58:425126 MockWrite data_writes[] = {
5127 MockWrite("GET / HTTP/1.1\r\n"
5128 "Host: www.google.com\r\n"
5129 "Connection: keep-alive\r\n"
5130 "FooHeader: Bar\r\n\r\n"),
5131 };
5132
5133 // Lastly, the server responds with the actual content.
5134 MockRead data_reads[] = {
5135 MockRead("HTTP/1.0 200 OK\r\n"),
5136 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5137 MockRead("Content-Length: 100\r\n\r\n"),
5138 MockRead(false, OK),
5139 };
5140
[email protected]31a2bfe2010-02-09 08:03:395141 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5142 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595143 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425144
[email protected]49639fa2011-12-20 23:22:415145 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425146
[email protected]49639fa2011-12-20 23:22:415147 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425148 EXPECT_EQ(ERR_IO_PENDING, rv);
5149
5150 rv = callback.WaitForResult();
5151 EXPECT_EQ(OK, rv);
5152}
5153
[email protected]270c6412010-03-29 22:02:475154TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475155 HttpRequestInfo request;
5156 request.method = "GET";
5157 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435158 request.extra_headers.SetHeader("referer", "www.foo.com");
5159 request.extra_headers.SetHeader("hEllo", "Kitty");
5160 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475161
[email protected]cb9bf6ca2011-01-28 13:15:275162 SessionDependencies session_deps;
5163 scoped_ptr<HttpTransaction> trans(
5164 new HttpNetworkTransaction(CreateSession(&session_deps)));
5165
[email protected]270c6412010-03-29 22:02:475166 MockWrite data_writes[] = {
5167 MockWrite("GET / HTTP/1.1\r\n"
5168 "Host: www.google.com\r\n"
5169 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165170 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475171 "hEllo: Kitty\r\n"
5172 "FoO: bar\r\n\r\n"),
5173 };
5174
5175 // Lastly, the server responds with the actual content.
5176 MockRead data_reads[] = {
5177 MockRead("HTTP/1.0 200 OK\r\n"),
5178 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5179 MockRead("Content-Length: 100\r\n\r\n"),
5180 MockRead(false, OK),
5181 };
5182
5183 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5184 data_writes, arraysize(data_writes));
5185 session_deps.socket_factory.AddSocketDataProvider(&data);
5186
[email protected]49639fa2011-12-20 23:22:415187 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:475188
[email protected]49639fa2011-12-20 23:22:415189 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:475190 EXPECT_EQ(ERR_IO_PENDING, rv);
5191
5192 rv = callback.WaitForResult();
5193 EXPECT_EQ(OK, rv);
5194}
5195
[email protected]9ef1d98e2012-02-14 00:34:125196// http://crbug.com/112682
[email protected]ee0b1012012-02-04 04:30:255197#if defined(OS_MACOSX)
[email protected]9ef1d98e2012-02-14 00:34:125198#define MAYBE_SOCKS4_HTTP_GET DISABLED_SOCKS4_HTTP_GET
[email protected]ee0b1012012-02-04 04:30:255199#else
5200#define MAYBE_SOCKS4_HTTP_GET SOCKS4_HTTP_GET
5201#endif
5202
5203TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275204 HttpRequestInfo request;
5205 request.method = "GET";
5206 request.url = GURL("http://www.google.com/");
5207 request.load_flags = 0;
5208
[email protected]80d6524d2009-08-18 03:58:095209 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005210 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025211
5212 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435213 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025214
[email protected]3cd17242009-06-23 02:59:025215 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5216 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5217
5218 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355219 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025220 MockWrite("GET / HTTP/1.1\r\n"
5221 "Host: www.google.com\r\n"
5222 "Connection: keep-alive\r\n\r\n")
5223 };
5224
5225 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595226 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025227 MockRead("HTTP/1.0 200 OK\r\n"),
5228 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5229 MockRead("Payload"),
5230 MockRead(false, OK)
5231 };
5232
[email protected]31a2bfe2010-02-09 08:03:395233 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5234 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595235 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025236
[email protected]49639fa2011-12-20 23:22:415237 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025238
[email protected]49639fa2011-12-20 23:22:415239 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025240 EXPECT_EQ(ERR_IO_PENDING, rv);
5241
5242 rv = callback.WaitForResult();
5243 EXPECT_EQ(OK, rv);
5244
5245 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505246 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025247
5248 std::string response_text;
5249 rv = ReadTransaction(trans.get(), &response_text);
5250 EXPECT_EQ(OK, rv);
5251 EXPECT_EQ("Payload", response_text);
5252}
5253
[email protected]9ef1d98e2012-02-14 00:34:125254// http://crbug.com/112682
[email protected]ee0b1012012-02-04 04:30:255255#if defined(OS_MACOSX)
[email protected]9ef1d98e2012-02-14 00:34:125256#define MAYBE_SOCKS4_SSL_GET DISABLED_SOCKS4_SSL_GET
[email protected]ee0b1012012-02-04 04:30:255257#else
5258#define MAYBE_SOCKS4_SSL_GET SOCKS4_SSL_GET
5259#endif
5260
5261TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275262 HttpRequestInfo request;
5263 request.method = "GET";
5264 request.url = GURL("https://www.google.com/");
5265 request.load_flags = 0;
5266
[email protected]80d6524d2009-08-18 03:58:095267 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005268 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025269
5270 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435271 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025272
[email protected]3cd17242009-06-23 02:59:025273 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5274 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5275
5276 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355277 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5278 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025279 MockWrite("GET / HTTP/1.1\r\n"
5280 "Host: www.google.com\r\n"
5281 "Connection: keep-alive\r\n\r\n")
5282 };
5283
5284 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355285 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5286 arraysize(read_buffer)),
5287 MockRead("HTTP/1.0 200 OK\r\n"),
5288 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5289 MockRead("Payload"),
5290 MockRead(false, OK)
5291 };
5292
[email protected]31a2bfe2010-02-09 08:03:395293 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5294 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595295 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355296
[email protected]5ecc992a42009-11-11 01:41:595297 SSLSocketDataProvider ssl(true, OK);
5298 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355299
[email protected]49639fa2011-12-20 23:22:415300 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355301
[email protected]49639fa2011-12-20 23:22:415302 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355303 EXPECT_EQ(ERR_IO_PENDING, rv);
5304
5305 rv = callback.WaitForResult();
5306 EXPECT_EQ(OK, rv);
5307
5308 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505309 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355310
5311 std::string response_text;
5312 rv = ReadTransaction(trans.get(), &response_text);
5313 EXPECT_EQ(OK, rv);
5314 EXPECT_EQ("Payload", response_text);
5315}
5316
5317TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275318 HttpRequestInfo request;
5319 request.method = "GET";
5320 request.url = GURL("http://www.google.com/");
5321 request.load_flags = 0;
5322
[email protected]80d6524d2009-08-18 03:58:095323 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005324 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355325
5326 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435327 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355328
[email protected]e0c27be2009-07-15 13:09:355329 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5330 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375331 const char kSOCKS5OkRequest[] = {
5332 0x05, // Version
5333 0x01, // Command (CONNECT)
5334 0x00, // Reserved.
5335 0x03, // Address type (DOMAINNAME).
5336 0x0E, // Length of domain (14)
5337 // Domain string:
5338 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5339 0x00, 0x50, // 16-bit port (80)
5340 };
[email protected]e0c27be2009-07-15 13:09:355341 const char kSOCKS5OkResponse[] =
5342 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5343
5344 MockWrite data_writes[] = {
5345 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5346 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5347 MockWrite("GET / HTTP/1.1\r\n"
5348 "Host: www.google.com\r\n"
5349 "Connection: keep-alive\r\n\r\n")
5350 };
5351
5352 MockRead data_reads[] = {
5353 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5354 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5355 MockRead("HTTP/1.0 200 OK\r\n"),
5356 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5357 MockRead("Payload"),
5358 MockRead(false, OK)
5359 };
5360
[email protected]31a2bfe2010-02-09 08:03:395361 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5362 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595363 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355364
[email protected]49639fa2011-12-20 23:22:415365 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355366
[email protected]49639fa2011-12-20 23:22:415367 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355368 EXPECT_EQ(ERR_IO_PENDING, rv);
5369
5370 rv = callback.WaitForResult();
5371 EXPECT_EQ(OK, rv);
5372
5373 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505374 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355375
5376 std::string response_text;
5377 rv = ReadTransaction(trans.get(), &response_text);
5378 EXPECT_EQ(OK, rv);
5379 EXPECT_EQ("Payload", response_text);
5380}
5381
5382TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275383 HttpRequestInfo request;
5384 request.method = "GET";
5385 request.url = GURL("https://www.google.com/");
5386 request.load_flags = 0;
5387
[email protected]80d6524d2009-08-18 03:58:095388 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005389 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355390
5391 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435392 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355393
[email protected]e0c27be2009-07-15 13:09:355394 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5395 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375396 const unsigned char kSOCKS5OkRequest[] = {
5397 0x05, // Version
5398 0x01, // Command (CONNECT)
5399 0x00, // Reserved.
5400 0x03, // Address type (DOMAINNAME).
5401 0x0E, // Length of domain (14)
5402 // Domain string:
5403 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5404 0x01, 0xBB, // 16-bit port (443)
5405 };
5406
[email protected]e0c27be2009-07-15 13:09:355407 const char kSOCKS5OkResponse[] =
5408 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5409
5410 MockWrite data_writes[] = {
5411 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5412 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5413 arraysize(kSOCKS5OkRequest)),
5414 MockWrite("GET / HTTP/1.1\r\n"
5415 "Host: www.google.com\r\n"
5416 "Connection: keep-alive\r\n\r\n")
5417 };
5418
5419 MockRead data_reads[] = {
5420 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5421 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025422 MockRead("HTTP/1.0 200 OK\r\n"),
5423 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5424 MockRead("Payload"),
5425 MockRead(false, OK)
5426 };
5427
[email protected]31a2bfe2010-02-09 08:03:395428 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5429 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595430 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025431
[email protected]5ecc992a42009-11-11 01:41:595432 SSLSocketDataProvider ssl(true, OK);
5433 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025434
[email protected]49639fa2011-12-20 23:22:415435 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025436
[email protected]49639fa2011-12-20 23:22:415437 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025438 EXPECT_EQ(ERR_IO_PENDING, rv);
5439
5440 rv = callback.WaitForResult();
5441 EXPECT_EQ(OK, rv);
5442
5443 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505444 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025445
5446 std::string response_text;
5447 rv = ReadTransaction(trans.get(), &response_text);
5448 EXPECT_EQ(OK, rv);
5449 EXPECT_EQ("Payload", response_text);
5450}
5451
[email protected]04e5be32009-06-26 20:00:315452// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065453
5454struct GroupNameTest {
5455 std::string proxy_server;
5456 std::string url;
5457 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185458 bool ssl;
[email protected]2d731a32010-04-29 01:04:065459};
5460
5461scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025462 SessionDependencies* session_deps) {
5463 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065464
[email protected]17291a022011-10-10 07:32:535465 HttpServerProperties* http_server_properties =
5466 session->http_server_properties();
5467 http_server_properties->SetAlternateProtocol(
[email protected]2d731a32010-04-29 01:04:065468 HostPortPair("host.with.alternate", 80), 443,
[email protected]8d2f7012012-02-16 00:08:045469 NPN_SPDY_21);
[email protected]2d731a32010-04-29 01:04:065470
5471 return session;
5472}
5473
5474int GroupNameTransactionHelper(
5475 const std::string& url,
5476 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065477 HttpRequestInfo request;
5478 request.method = "GET";
5479 request.url = GURL(url);
5480 request.load_flags = 0;
5481
[email protected]cb9bf6ca2011-01-28 13:15:275482 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5483
[email protected]49639fa2011-12-20 23:22:415484 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:065485
5486 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:415487 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:065488}
5489
5490TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5491 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315492 {
[email protected]2d731a32010-04-29 01:04:065493 "", // unused
[email protected]04e5be32009-06-26 20:00:315494 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545495 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185496 false,
[email protected]2ff8b312010-04-26 22:20:545497 },
5498 {
[email protected]2d731a32010-04-29 01:04:065499 "", // unused
[email protected]2ff8b312010-04-26 22:20:545500 "http://[2001:1418:13:1::25]/direct",
5501 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185502 false,
[email protected]04e5be32009-06-26 20:00:315503 },
[email protected]04e5be32009-06-26 20:00:315504
5505 // SSL Tests
5506 {
[email protected]2d731a32010-04-29 01:04:065507 "", // unused
[email protected]04e5be32009-06-26 20:00:315508 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025509 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185510 true,
[email protected]04e5be32009-06-26 20:00:315511 },
5512 {
[email protected]2d731a32010-04-29 01:04:065513 "", // unused
5514 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025515 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185516 true,
[email protected]04e5be32009-06-26 20:00:315517 },
5518 {
[email protected]2d731a32010-04-29 01:04:065519 "", // unused
[email protected]2ff8b312010-04-26 22:20:545520 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025521 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185522 true,
[email protected]2ff8b312010-04-26 22:20:545523 },
[email protected]2d731a32010-04-29 01:04:065524 };
[email protected]2ff8b312010-04-26 22:20:545525
[email protected]8e6441ca2010-08-19 05:56:385526 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065527
5528 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025529 SessionDependencies session_deps(
5530 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065531 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025532 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065533
5534 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285535 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5536 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135537 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345538 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025539 MockClientSocketPoolManager* mock_pool_manager =
5540 new MockClientSocketPoolManager;
5541 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
5542 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
5543 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065544
5545 EXPECT_EQ(ERR_IO_PENDING,
5546 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185547 if (tests[i].ssl)
5548 EXPECT_EQ(tests[i].expected_group_name,
5549 ssl_conn_pool->last_group_name_received());
5550 else
5551 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285552 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065553 }
5554
[email protected]8e6441ca2010-08-19 05:56:385555 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065556}
5557
5558TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5559 const GroupNameTest tests[] = {
5560 {
5561 "http_proxy",
5562 "http://www.google.com/http_proxy_normal",
5563 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185564 false,
[email protected]2d731a32010-04-29 01:04:065565 },
5566
5567 // SSL Tests
5568 {
5569 "http_proxy",
5570 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025571 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185572 true,
[email protected]2d731a32010-04-29 01:04:065573 },
[email protected]af3490e2010-10-16 21:02:295574
[email protected]9faeded92010-04-29 20:03:055575 {
5576 "http_proxy",
5577 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025578 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185579 true,
[email protected]9faeded92010-04-29 20:03:055580 },
[email protected]2d731a32010-04-29 01:04:065581 };
5582
[email protected]8e6441ca2010-08-19 05:56:385583 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065584
5585 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025586 SessionDependencies session_deps(
5587 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065588 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025589 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065590
5591 HttpNetworkSessionPeer peer(session);
5592
[email protected]e60e47a2010-07-14 03:37:185593 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135594 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345595 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135596 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345597 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025598
5599 MockClientSocketPoolManager* mock_pool_manager =
5600 new MockClientSocketPoolManager;
5601 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
5602 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5603 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065604
5605 EXPECT_EQ(ERR_IO_PENDING,
5606 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185607 if (tests[i].ssl)
5608 EXPECT_EQ(tests[i].expected_group_name,
5609 ssl_conn_pool->last_group_name_received());
5610 else
5611 EXPECT_EQ(tests[i].expected_group_name,
5612 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065613 }
5614
[email protected]8e6441ca2010-08-19 05:56:385615 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065616}
5617
5618TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5619 const GroupNameTest tests[] = {
5620 {
5621 "socks4://socks_proxy:1080",
5622 "http://www.google.com/socks4_direct",
5623 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185624 false,
[email protected]2d731a32010-04-29 01:04:065625 },
5626 {
5627 "socks5://socks_proxy:1080",
5628 "http://www.google.com/socks5_direct",
5629 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185630 false,
[email protected]2d731a32010-04-29 01:04:065631 },
5632
5633 // SSL Tests
5634 {
5635 "socks4://socks_proxy:1080",
5636 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025637 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185638 true,
[email protected]2d731a32010-04-29 01:04:065639 },
5640 {
5641 "socks5://socks_proxy:1080",
5642 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025643 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185644 true,
[email protected]2d731a32010-04-29 01:04:065645 },
[email protected]af3490e2010-10-16 21:02:295646
[email protected]9faeded92010-04-29 20:03:055647 {
5648 "socks4://socks_proxy:1080",
5649 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025650 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185651 true,
[email protected]9faeded92010-04-29 20:03:055652 },
[email protected]04e5be32009-06-26 20:00:315653 };
5654
[email protected]8e6441ca2010-08-19 05:56:385655 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545656
[email protected]04e5be32009-06-26 20:00:315657 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025658 SessionDependencies session_deps(
5659 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065660 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025661 SetupSessionForGroupNameTests(&session_deps));
5662
[email protected]2d731a32010-04-29 01:04:065663 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315664
[email protected]e60e47a2010-07-14 03:37:185665 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135666 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345667 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135668 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345669 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025670
5671 MockClientSocketPoolManager* mock_pool_manager =
5672 new MockClientSocketPoolManager;
5673 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
5674 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5675 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]04e5be32009-06-26 20:00:315676
[email protected]5695b8c2009-09-30 21:36:435677 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315678
[email protected]2d731a32010-04-29 01:04:065679 EXPECT_EQ(ERR_IO_PENDING,
5680 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185681 if (tests[i].ssl)
5682 EXPECT_EQ(tests[i].expected_group_name,
5683 ssl_conn_pool->last_group_name_received());
5684 else
5685 EXPECT_EQ(tests[i].expected_group_name,
5686 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315687 }
[email protected]2ff8b312010-04-26 22:20:545688
[email protected]8e6441ca2010-08-19 05:56:385689 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315690}
5691
[email protected]9172a982009-06-06 00:30:255692TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275693 HttpRequestInfo request;
5694 request.method = "GET";
5695 request.url = GURL("http://www.google.com/");
5696
[email protected]5c6a17e2009-06-10 00:54:545697 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005698 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325699
[email protected]69719062010-01-05 20:09:215700 // This simulates failure resolving all hostnames; that means we will fail
5701 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325702 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5703
[email protected]9172a982009-06-06 00:30:255704 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435705 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255706
[email protected]49639fa2011-12-20 23:22:415707 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:255708
[email protected]49639fa2011-12-20 23:22:415709 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:255710 EXPECT_EQ(ERR_IO_PENDING, rv);
5711
[email protected]9172a982009-06-06 00:30:255712 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015713 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255714}
5715
[email protected]685af592010-05-11 19:31:245716// Base test to make sure that when the load flags for a request specify to
5717// bypass the cache, the DNS cache is not used.
5718void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275719 // Issue a request, asking to bypass the cache(s).
5720 HttpRequestInfo request;
5721 request.method = "GET";
5722 request.load_flags = load_flags;
5723 request.url = GURL("http://www.google.com/");
5724
[email protected]3b9cca42009-06-16 01:08:285725 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325726
[email protected]a2c2fb92009-07-18 07:31:045727 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545728 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325729
[email protected]3b9cca42009-06-16 01:08:285730 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435731 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285732
[email protected]6e78dfb2011-07-28 21:34:475733 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285734 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:295735 TestCompletionCallback callback;
[email protected]94a0d3d92009-06-27 01:50:145736 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105737 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295738 callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:475739 EXPECT_EQ(ERR_IO_PENDING, rv);
5740 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285741 EXPECT_EQ(OK, rv);
5742
5743 // Verify that it was added to host cache, by doing a subsequent async lookup
5744 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465745 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105746 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295747 callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325748 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285749
5750 // Inject a failure the next time that "www.google.com" is resolved. This way
5751 // we can tell if the next lookup hit the cache, or the "network".
5752 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325753 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285754
5755 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5756 // first read -- this won't be reached as the host resolution will fail first.
5757 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395758 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595759 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285760
[email protected]3b9cca42009-06-16 01:08:285761 // Run the request.
[email protected]49639fa2011-12-20 23:22:415762 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285763 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:415764 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285765
5766 // If we bypassed the cache, we would have gotten a failure while resolving
5767 // "www.google.com".
5768 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5769}
5770
[email protected]685af592010-05-11 19:31:245771// There are multiple load flags that should trigger the host cache bypass.
5772// Test each in isolation:
5773TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5774 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5775}
5776
5777TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5778 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5779}
5780
5781TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5782 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5783}
5784
[email protected]0877e3d2009-10-17 22:29:575785// Make sure we can handle an error when writing the request.
5786TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5787 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275788 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575789
5790 HttpRequestInfo request;
5791 request.method = "GET";
5792 request.url = GURL("http://www.foo.com/");
5793 request.load_flags = 0;
5794
5795 MockWrite write_failure[] = {
5796 MockWrite(true, ERR_CONNECTION_RESET),
5797 };
[email protected]31a2bfe2010-02-09 08:03:395798 StaticSocketDataProvider data(NULL, 0,
5799 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595800 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575801
[email protected]49639fa2011-12-20 23:22:415802 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575803
5804 scoped_ptr<HttpTransaction> trans(
5805 new HttpNetworkTransaction(CreateSession(&session_deps)));
5806
[email protected]49639fa2011-12-20 23:22:415807 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575808 EXPECT_EQ(ERR_IO_PENDING, rv);
5809
5810 rv = callback.WaitForResult();
5811 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5812}
5813
5814// Check that a connection closed after the start of the headers finishes ok.
5815TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5816 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275817 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575818
5819 HttpRequestInfo request;
5820 request.method = "GET";
5821 request.url = GURL("http://www.foo.com/");
5822 request.load_flags = 0;
5823
5824 MockRead data_reads[] = {
5825 MockRead("HTTP/1."),
5826 MockRead(false, OK),
5827 };
5828
[email protected]31a2bfe2010-02-09 08:03:395829 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595830 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575831
[email protected]49639fa2011-12-20 23:22:415832 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575833
5834 scoped_ptr<HttpTransaction> trans(
5835 new HttpNetworkTransaction(CreateSession(&session_deps)));
5836
[email protected]49639fa2011-12-20 23:22:415837 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575838 EXPECT_EQ(ERR_IO_PENDING, rv);
5839
5840 rv = callback.WaitForResult();
5841 EXPECT_EQ(OK, rv);
5842
5843 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505844 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:575845
5846 EXPECT_TRUE(response->headers != NULL);
5847 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5848
5849 std::string response_data;
5850 rv = ReadTransaction(trans.get(), &response_data);
5851 EXPECT_EQ(OK, rv);
5852 EXPECT_EQ("", response_data);
5853}
5854
5855// Make sure that a dropped connection while draining the body for auth
5856// restart does the right thing.
5857TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5858 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275859 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575860
5861 HttpRequestInfo request;
5862 request.method = "GET";
5863 request.url = GURL("http://www.google.com/");
5864 request.load_flags = 0;
5865
5866 MockWrite data_writes1[] = {
5867 MockWrite("GET / HTTP/1.1\r\n"
5868 "Host: www.google.com\r\n"
5869 "Connection: keep-alive\r\n\r\n"),
5870 };
5871
5872 MockRead data_reads1[] = {
5873 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5874 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5875 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5876 MockRead("Content-Length: 14\r\n\r\n"),
5877 MockRead("Unauth"),
5878 MockRead(true, ERR_CONNECTION_RESET),
5879 };
5880
[email protected]31a2bfe2010-02-09 08:03:395881 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5882 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595883 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575884
5885 // After calling trans->RestartWithAuth(), this is the request we should
5886 // be issuing -- the final header line contains the credentials.
5887 MockWrite data_writes2[] = {
5888 MockWrite("GET / HTTP/1.1\r\n"
5889 "Host: www.google.com\r\n"
5890 "Connection: keep-alive\r\n"
5891 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5892 };
5893
5894 // Lastly, the server responds with the actual content.
5895 MockRead data_reads2[] = {
5896 MockRead("HTTP/1.1 200 OK\r\n"),
5897 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5898 MockRead("Content-Length: 100\r\n\r\n"),
5899 MockRead(false, OK),
5900 };
5901
[email protected]31a2bfe2010-02-09 08:03:395902 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5903 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595904 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575905
[email protected]49639fa2011-12-20 23:22:415906 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:575907
[email protected]0b0bf032010-09-21 18:08:505908 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5909
[email protected]49639fa2011-12-20 23:22:415910 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575911 EXPECT_EQ(ERR_IO_PENDING, rv);
5912
5913 rv = callback1.WaitForResult();
5914 EXPECT_EQ(OK, rv);
5915
5916 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505917 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045918 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:575919
[email protected]49639fa2011-12-20 23:22:415920 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:575921
[email protected]49639fa2011-12-20 23:22:415922 rv = trans->RestartWithAuth(
5923 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:575924 EXPECT_EQ(ERR_IO_PENDING, rv);
5925
5926 rv = callback2.WaitForResult();
5927 EXPECT_EQ(OK, rv);
5928
5929 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505930 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:575931 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5932 EXPECT_EQ(100, response->headers->GetContentLength());
5933}
5934
5935// Test HTTPS connections going through a proxy that sends extra data.
5936TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005937 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575938
5939 HttpRequestInfo request;
5940 request.method = "GET";
5941 request.url = GURL("https://www.google.com/");
5942 request.load_flags = 0;
5943
5944 MockRead proxy_reads[] = {
5945 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5946 MockRead(false, OK)
5947 };
5948
[email protected]31a2bfe2010-02-09 08:03:395949 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595950 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575951
[email protected]5ecc992a42009-11-11 01:41:595952 session_deps.socket_factory.AddSocketDataProvider(&data);
5953 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575954
[email protected]49639fa2011-12-20 23:22:415955 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575956
5957 session_deps.socket_factory.ResetNextMockIndexes();
5958
5959 scoped_ptr<HttpTransaction> trans(
5960 new HttpNetworkTransaction(CreateSession(&session_deps)));
5961
[email protected]49639fa2011-12-20 23:22:415962 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575963 EXPECT_EQ(ERR_IO_PENDING, rv);
5964
5965 rv = callback.WaitForResult();
5966 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5967}
5968
[email protected]e22e1362009-11-23 21:31:125969TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465970 HttpRequestInfo request;
5971 request.method = "GET";
5972 request.url = GURL("http://www.google.com/");
5973 request.load_flags = 0;
5974
[email protected]cb9bf6ca2011-01-28 13:15:275975 SessionDependencies session_deps;
5976 scoped_ptr<HttpTransaction> trans(
5977 new HttpNetworkTransaction(CreateSession(&session_deps)));
5978
[email protected]e22e1362009-11-23 21:31:125979 MockRead data_reads[] = {
5980 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
5981 MockRead(false, OK),
5982 };
[email protected]9492e4a2010-02-24 00:58:465983
5984 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
5985 session_deps.socket_factory.AddSocketDataProvider(&data);
5986
[email protected]49639fa2011-12-20 23:22:415987 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:465988
[email protected]49639fa2011-12-20 23:22:415989 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:465990 EXPECT_EQ(ERR_IO_PENDING, rv);
5991
5992 EXPECT_EQ(OK, callback.WaitForResult());
5993
5994 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505995 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:465996
5997 EXPECT_TRUE(response->headers != NULL);
5998 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5999
6000 std::string response_data;
6001 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f001bd6a2011-12-08 04:31:376002 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126003}
6004
[email protected]95d88ffe2010-02-04 21:25:336005TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336006 HttpRequestInfo request;
6007 request.method = "POST";
6008 request.url = GURL("http://www.google.com/upload");
6009 request.upload_data = new UploadData;
6010 request.load_flags = 0;
6011
[email protected]cb9bf6ca2011-01-28 13:15:276012 SessionDependencies session_deps;
6013 scoped_ptr<HttpTransaction> trans(
6014 new HttpNetworkTransaction(CreateSession(&session_deps)));
6015
[email protected]95d88ffe2010-02-04 21:25:336016 FilePath temp_file_path;
6017 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6018 const uint64 kFakeSize = 100000; // file is actually blank
6019
6020 std::vector<UploadData::Element> elements;
6021 UploadData::Element element;
6022 element.SetToFilePath(temp_file_path);
6023 element.SetContentLength(kFakeSize);
6024 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536025 request.upload_data->SetElements(elements);
[email protected]1dce7082012-02-10 07:39:116026 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLengthSync());
[email protected]95d88ffe2010-02-04 21:25:336027
6028 MockRead data_reads[] = {
6029 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6030 MockRead("hello world"),
6031 MockRead(false, OK),
6032 };
[email protected]31a2bfe2010-02-09 08:03:396033 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336034 session_deps.socket_factory.AddSocketDataProvider(&data);
6035
[email protected]49639fa2011-12-20 23:22:416036 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:336037
[email protected]49639fa2011-12-20 23:22:416038 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336039 EXPECT_EQ(ERR_IO_PENDING, rv);
6040
6041 rv = callback.WaitForResult();
6042 EXPECT_EQ(OK, rv);
6043
6044 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506045 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:336046
6047 EXPECT_TRUE(response->headers != NULL);
6048 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6049
6050 std::string response_data;
6051 rv = ReadTransaction(trans.get(), &response_data);
6052 EXPECT_EQ(OK, rv);
6053 EXPECT_EQ("hello world", response_data);
6054
6055 file_util::Delete(temp_file_path, false);
6056}
6057
[email protected]6624b4622010-03-29 19:58:366058TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276059 HttpRequestInfo request;
6060 request.method = "POST";
6061 request.url = GURL("http://www.google.com/upload");
6062 request.upload_data = new UploadData;
6063 request.load_flags = 0;
6064
[email protected]6624b4622010-03-29 19:58:366065 // If we try to upload an unreadable file, the network stack should report
6066 // the file size as zero and upload zero bytes for that file.
6067 SessionDependencies session_deps;
6068 scoped_ptr<HttpTransaction> trans(
6069 new HttpNetworkTransaction(CreateSession(&session_deps)));
6070
6071 FilePath temp_file;
6072 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6073 std::string temp_file_content("Unreadable file.");
6074 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6075 temp_file_content.length()));
6076 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6077
[email protected]6624b4622010-03-29 19:58:366078 std::vector<UploadData::Element> elements;
6079 UploadData::Element element;
6080 element.SetToFilePath(temp_file);
6081 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536082 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366083
6084 MockRead data_reads[] = {
6085 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6086 MockRead(false, OK),
6087 };
6088 MockWrite data_writes[] = {
6089 MockWrite("POST /upload HTTP/1.1\r\n"
6090 "Host: www.google.com\r\n"
6091 "Connection: keep-alive\r\n"
6092 "Content-Length: 0\r\n\r\n"),
6093 MockWrite(false, OK),
6094 };
6095 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6096 arraysize(data_writes));
6097 session_deps.socket_factory.AddSocketDataProvider(&data);
6098
[email protected]49639fa2011-12-20 23:22:416099 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:366100
[email protected]49639fa2011-12-20 23:22:416101 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366102 EXPECT_EQ(ERR_IO_PENDING, rv);
6103
6104 rv = callback.WaitForResult();
6105 EXPECT_EQ(OK, rv);
6106
6107 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506108 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366109 EXPECT_TRUE(response->headers != NULL);
6110 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6111
6112 file_util::Delete(temp_file, false);
6113}
6114
6115TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276116 HttpRequestInfo request;
6117 request.method = "POST";
6118 request.url = GURL("http://www.google.com/upload");
6119 request.upload_data = new UploadData;
6120 request.load_flags = 0;
6121
[email protected]6624b4622010-03-29 19:58:366122 SessionDependencies session_deps;
6123 scoped_ptr<HttpTransaction> trans(
6124 new HttpNetworkTransaction(CreateSession(&session_deps)));
6125
6126 FilePath temp_file;
6127 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6128 std::string temp_file_contents("Unreadable file.");
6129 std::string unreadable_contents(temp_file_contents.length(), '\0');
6130 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6131 temp_file_contents.length()));
6132
[email protected]6624b4622010-03-29 19:58:366133 std::vector<UploadData::Element> elements;
6134 UploadData::Element element;
6135 element.SetToFilePath(temp_file);
6136 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536137 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366138
6139 MockRead data_reads[] = {
6140 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6141 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6142 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6143
6144 MockRead("HTTP/1.1 200 OK\r\n"),
6145 MockRead("Content-Length: 0\r\n\r\n"),
6146 MockRead(false, OK),
6147 };
6148 MockWrite data_writes[] = {
6149 MockWrite("POST /upload HTTP/1.1\r\n"
6150 "Host: www.google.com\r\n"
6151 "Connection: keep-alive\r\n"
6152 "Content-Length: 16\r\n\r\n"),
6153 MockWrite(false, temp_file_contents.c_str()),
6154
6155 MockWrite("POST /upload HTTP/1.1\r\n"
6156 "Host: www.google.com\r\n"
6157 "Connection: keep-alive\r\n"
6158 "Content-Length: 16\r\n"
6159 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6160 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6161 MockWrite(false, OK),
6162 };
6163 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6164 arraysize(data_writes));
6165 session_deps.socket_factory.AddSocketDataProvider(&data);
6166
[email protected]49639fa2011-12-20 23:22:416167 TestCompletionCallback callback1;
[email protected]6624b4622010-03-29 19:58:366168
[email protected]49639fa2011-12-20 23:22:416169 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366170 EXPECT_EQ(ERR_IO_PENDING, rv);
6171
6172 rv = callback1.WaitForResult();
6173 EXPECT_EQ(OK, rv);
6174
6175 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:046176 ASSERT_TRUE(response != NULL);
6177 ASSERT_TRUE(response->headers != NULL);
[email protected]6624b4622010-03-29 19:58:366178 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
[email protected]79cb5c12011-09-12 13:12:046179 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]6624b4622010-03-29 19:58:366180
6181 // Now make the file unreadable and try again.
6182 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6183
[email protected]49639fa2011-12-20 23:22:416184 TestCompletionCallback callback2;
[email protected]6624b4622010-03-29 19:58:366185
[email protected]49639fa2011-12-20 23:22:416186 rv = trans->RestartWithAuth(
6187 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]6624b4622010-03-29 19:58:366188 EXPECT_EQ(ERR_IO_PENDING, rv);
6189
6190 rv = callback2.WaitForResult();
6191 EXPECT_EQ(OK, rv);
6192
6193 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506194 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366195 EXPECT_TRUE(response->headers != NULL);
6196 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6197 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6198
6199 file_util::Delete(temp_file, false);
6200}
6201
[email protected]aeefc9e82010-02-19 16:18:276202// Tests that changes to Auth realms are treated like auth rejections.
6203TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6204 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276205
6206 HttpRequestInfo request;
6207 request.method = "GET";
6208 request.url = GURL("http://www.google.com/");
6209 request.load_flags = 0;
6210
6211 // First transaction will request a resource and receive a Basic challenge
6212 // with realm="first_realm".
6213 MockWrite data_writes1[] = {
6214 MockWrite("GET / HTTP/1.1\r\n"
6215 "Host: www.google.com\r\n"
6216 "Connection: keep-alive\r\n"
6217 "\r\n"),
6218 };
6219 MockRead data_reads1[] = {
6220 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6221 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6222 "\r\n"),
6223 };
6224
6225 // After calling trans->RestartWithAuth(), provide an Authentication header
6226 // for first_realm. The server will reject and provide a challenge with
6227 // second_realm.
6228 MockWrite data_writes2[] = {
6229 MockWrite("GET / HTTP/1.1\r\n"
6230 "Host: www.google.com\r\n"
6231 "Connection: keep-alive\r\n"
6232 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6233 "\r\n"),
6234 };
6235 MockRead data_reads2[] = {
6236 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6237 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6238 "\r\n"),
6239 };
6240
6241 // This again fails, and goes back to first_realm. Make sure that the
6242 // entry is removed from cache.
6243 MockWrite data_writes3[] = {
6244 MockWrite("GET / HTTP/1.1\r\n"
6245 "Host: www.google.com\r\n"
6246 "Connection: keep-alive\r\n"
6247 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6248 "\r\n"),
6249 };
6250 MockRead data_reads3[] = {
6251 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6252 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6253 "\r\n"),
6254 };
6255
6256 // Try one last time (with the correct password) and get the resource.
6257 MockWrite data_writes4[] = {
6258 MockWrite("GET / HTTP/1.1\r\n"
6259 "Host: www.google.com\r\n"
6260 "Connection: keep-alive\r\n"
6261 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6262 "\r\n"),
6263 };
6264 MockRead data_reads4[] = {
6265 MockRead("HTTP/1.1 200 OK\r\n"
6266 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506267 "Content-Length: 5\r\n"
6268 "\r\n"
6269 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276270 };
6271
6272 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6273 data_writes1, arraysize(data_writes1));
6274 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6275 data_writes2, arraysize(data_writes2));
6276 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6277 data_writes3, arraysize(data_writes3));
6278 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6279 data_writes4, arraysize(data_writes4));
6280 session_deps.socket_factory.AddSocketDataProvider(&data1);
6281 session_deps.socket_factory.AddSocketDataProvider(&data2);
6282 session_deps.socket_factory.AddSocketDataProvider(&data3);
6283 session_deps.socket_factory.AddSocketDataProvider(&data4);
6284
[email protected]49639fa2011-12-20 23:22:416285 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:276286
[email protected]0b0bf032010-09-21 18:08:506287 scoped_ptr<HttpTransaction> trans(
6288 new HttpNetworkTransaction(CreateSession(&session_deps)));
6289
[email protected]aeefc9e82010-02-19 16:18:276290 // Issue the first request with Authorize headers. There should be a
6291 // password prompt for first_realm waiting to be filled in after the
6292 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416293 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276294 EXPECT_EQ(ERR_IO_PENDING, rv);
6295 rv = callback1.WaitForResult();
6296 EXPECT_EQ(OK, rv);
6297 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506298 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046299 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6300 ASSERT_FALSE(challenge == NULL);
6301 EXPECT_FALSE(challenge->is_proxy);
6302 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6303 EXPECT_EQ("first_realm", challenge->realm);
6304 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276305
6306 // Issue the second request with an incorrect password. There should be a
6307 // password prompt for second_realm waiting to be filled in after the
6308 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416309 TestCompletionCallback callback2;
6310 rv = trans->RestartWithAuth(
6311 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:276312 EXPECT_EQ(ERR_IO_PENDING, rv);
6313 rv = callback2.WaitForResult();
6314 EXPECT_EQ(OK, rv);
6315 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506316 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046317 challenge = response->auth_challenge.get();
6318 ASSERT_FALSE(challenge == NULL);
6319 EXPECT_FALSE(challenge->is_proxy);
6320 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6321 EXPECT_EQ("second_realm", challenge->realm);
6322 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276323
6324 // Issue the third request with another incorrect password. There should be
6325 // a password prompt for first_realm waiting to be filled in. If the password
6326 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6327 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:416328 TestCompletionCallback callback3;
6329 rv = trans->RestartWithAuth(
6330 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:276331 EXPECT_EQ(ERR_IO_PENDING, rv);
6332 rv = callback3.WaitForResult();
6333 EXPECT_EQ(OK, rv);
6334 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506335 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046336 challenge = response->auth_challenge.get();
6337 ASSERT_FALSE(challenge == NULL);
6338 EXPECT_FALSE(challenge->is_proxy);
6339 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6340 EXPECT_EQ("first_realm", challenge->realm);
6341 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276342
6343 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:416344 TestCompletionCallback callback4;
6345 rv = trans->RestartWithAuth(
6346 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:276347 EXPECT_EQ(ERR_IO_PENDING, rv);
6348 rv = callback4.WaitForResult();
6349 EXPECT_EQ(OK, rv);
6350 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506351 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:276352 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6353}
6354
[email protected]564b4912010-03-09 16:30:426355TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]5285d972011-10-18 18:56:346356 HttpStreamFactory::set_next_protos(MakeNextProtos("foo", "bar", NULL));
[email protected]8e6441ca2010-08-19 05:56:386357 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426358
[email protected]564b4912010-03-09 16:30:426359 SessionDependencies session_deps;
6360
6361 MockRead data_reads[] = {
6362 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356363 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426364 MockRead("hello world"),
6365 MockRead(false, OK),
6366 };
6367
6368 HttpRequestInfo request;
6369 request.method = "GET";
6370 request.url = GURL("http://www.google.com/");
6371 request.load_flags = 0;
6372
6373 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6374
6375 session_deps.socket_factory.AddSocketDataProvider(&data);
6376
[email protected]49639fa2011-12-20 23:22:416377 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426378
6379 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6380 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6381
[email protected]49639fa2011-12-20 23:22:416382 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426383 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536384
[email protected]2fbaecf22010-07-22 22:20:356385 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]17291a022011-10-10 07:32:536386 const HttpServerProperties& http_server_properties =
6387 *session->http_server_properties();
[email protected]564b4912010-03-09 16:30:426388 EXPECT_FALSE(
[email protected]17291a022011-10-10 07:32:536389 http_server_properties.HasAlternateProtocol(http_host_port_pair));
[email protected]564b4912010-03-09 16:30:426390
6391 EXPECT_EQ(OK, callback.WaitForResult());
6392
6393 const HttpResponseInfo* response = trans->GetResponseInfo();
6394 ASSERT_TRUE(response != NULL);
6395 ASSERT_TRUE(response->headers != NULL);
6396 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536397 EXPECT_FALSE(response->was_fetched_via_spdy);
6398 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426399
6400 std::string response_data;
6401 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6402 EXPECT_EQ("hello world", response_data);
6403
[email protected]17291a022011-10-10 07:32:536404 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6405 const PortAlternateProtocolPair alternate =
6406 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6407 PortAlternateProtocolPair expected_alternate;
[email protected]564b4912010-03-09 16:30:426408 expected_alternate.port = 443;
[email protected]8d2f7012012-02-16 00:08:046409 expected_alternate.protocol = NPN_SPDY_21;
[email protected]564b4912010-03-09 16:30:426410 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426411
[email protected]8e6441ca2010-08-19 05:56:386412 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]5285d972011-10-18 18:56:346413 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]564b4912010-03-09 16:30:426414}
6415
[email protected]8b95ed62011-03-18 18:12:036416TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386417 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426418 SessionDependencies session_deps;
6419
6420 HttpRequestInfo request;
6421 request.method = "GET";
6422 request.url = GURL("http://www.google.com/");
6423 request.load_flags = 0;
6424
[email protected]d973e99a2012-02-17 21:02:366425 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:426426 StaticSocketDataProvider first_data;
6427 first_data.set_connect_data(mock_connect);
6428 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6429
6430 MockRead data_reads[] = {
6431 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6432 MockRead("hello world"),
6433 MockRead(true, OK),
6434 };
6435 StaticSocketDataProvider second_data(
6436 data_reads, arraysize(data_reads), NULL, 0);
6437 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6438
[email protected]564b4912010-03-09 16:30:426439 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6440
[email protected]17291a022011-10-10 07:32:536441 HttpServerProperties* http_server_properties =
6442 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116443 // Port must be < 1024, or the header will be ignored (since initial port was
6444 // port 80 (another restricted port).
[email protected]17291a022011-10-10 07:32:536445 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116446 HostPortPair::FromURL(request.url),
6447 666 /* port is ignored by MockConnect anyway */,
[email protected]8d2f7012012-02-16 00:08:046448 NPN_SPDY_21);
[email protected]564b4912010-03-09 16:30:426449
6450 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416451 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426452
[email protected]49639fa2011-12-20 23:22:416453 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426454 EXPECT_EQ(ERR_IO_PENDING, rv);
6455 EXPECT_EQ(OK, callback.WaitForResult());
6456
6457 const HttpResponseInfo* response = trans->GetResponseInfo();
6458 ASSERT_TRUE(response != NULL);
6459 ASSERT_TRUE(response->headers != NULL);
6460 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6461
6462 std::string response_data;
6463 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6464 EXPECT_EQ("hello world", response_data);
6465
[email protected]17291a022011-10-10 07:32:536466 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116467 HostPortPair::FromURL(request.url)));
[email protected]17291a022011-10-10 07:32:536468 const PortAlternateProtocolPair alternate =
6469 http_server_properties->GetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116470 HostPortPair::FromURL(request.url));
[email protected]17291a022011-10-10 07:32:536471 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386472 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426473}
6474
[email protected]3912662a32011-10-04 00:51:116475TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6476 // Ensure that we're not allowed to redirect traffic via an alternate
6477 // protocol to an unrestricted (port >= 1024) when the original traffic was
6478 // on a restricted port (port < 1024). Ensure that we can redirect in all
6479 // other cases.
6480 HttpStreamFactory::set_use_alternate_protocols(true);
6481 SessionDependencies session_deps;
6482
6483 HttpRequestInfo restricted_port_request;
6484 restricted_port_request.method = "GET";
6485 restricted_port_request.url = GURL("http://www.google.com:1023/");
6486 restricted_port_request.load_flags = 0;
6487
[email protected]d973e99a2012-02-17 21:02:366488 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116489 StaticSocketDataProvider first_data;
6490 first_data.set_connect_data(mock_connect);
6491 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6492
6493 MockRead data_reads[] = {
6494 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6495 MockRead("hello world"),
6496 MockRead(true, OK),
6497 };
6498 StaticSocketDataProvider second_data(
6499 data_reads, arraysize(data_reads), NULL, 0);
6500 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6501
6502 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6503
[email protected]17291a022011-10-10 07:32:536504 HttpServerProperties* http_server_properties =
6505 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116506 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536507 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116508 HostPortPair::FromURL(restricted_port_request.url),
6509 kUnrestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046510 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116511
6512 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416513 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116514
[email protected]49639fa2011-12-20 23:22:416515 int rv = trans->Start(
6516 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116517 EXPECT_EQ(ERR_IO_PENDING, rv);
6518 // Invalid change to unrestricted port should fail.
6519 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6520
6521 HttpStreamFactory::set_use_alternate_protocols(false);
6522}
6523
6524TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6525 // Ensure that we're not allowed to redirect traffic via an alternate
6526 // protocol to an unrestricted (port >= 1024) when the original traffic was
6527 // on a restricted port (port < 1024). Ensure that we can redirect in all
6528 // other cases.
6529 HttpStreamFactory::set_use_alternate_protocols(true);
6530 SessionDependencies session_deps;
6531
6532 HttpRequestInfo restricted_port_request;
6533 restricted_port_request.method = "GET";
6534 restricted_port_request.url = GURL("http://www.google.com:1023/");
6535 restricted_port_request.load_flags = 0;
6536
[email protected]d973e99a2012-02-17 21:02:366537 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116538 StaticSocketDataProvider first_data;
6539 first_data.set_connect_data(mock_connect);
6540 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6541
6542 MockRead data_reads[] = {
6543 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6544 MockRead("hello world"),
6545 MockRead(true, OK),
6546 };
6547 StaticSocketDataProvider second_data(
6548 data_reads, arraysize(data_reads), NULL, 0);
6549 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6550
6551 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6552
[email protected]17291a022011-10-10 07:32:536553 HttpServerProperties* http_server_properties =
6554 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116555 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536556 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116557 HostPortPair::FromURL(restricted_port_request.url),
6558 kRestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046559 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116560
6561 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416562 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116563
[email protected]49639fa2011-12-20 23:22:416564 int rv = trans->Start(
6565 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116566 EXPECT_EQ(ERR_IO_PENDING, rv);
6567 // Valid change to restricted port should pass.
6568 EXPECT_EQ(OK, callback.WaitForResult());
6569
6570 HttpStreamFactory::set_use_alternate_protocols(false);
6571}
6572
6573TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6574 // Ensure that we're not allowed to redirect traffic via an alternate
6575 // protocol to an unrestricted (port >= 1024) when the original traffic was
6576 // on a restricted port (port < 1024). Ensure that we can redirect in all
6577 // other cases.
6578 HttpStreamFactory::set_use_alternate_protocols(true);
6579 SessionDependencies session_deps;
6580
6581 HttpRequestInfo unrestricted_port_request;
6582 unrestricted_port_request.method = "GET";
6583 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6584 unrestricted_port_request.load_flags = 0;
6585
[email protected]d973e99a2012-02-17 21:02:366586 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116587 StaticSocketDataProvider first_data;
6588 first_data.set_connect_data(mock_connect);
6589 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6590
6591 MockRead data_reads[] = {
6592 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6593 MockRead("hello world"),
6594 MockRead(true, OK),
6595 };
6596 StaticSocketDataProvider second_data(
6597 data_reads, arraysize(data_reads), NULL, 0);
6598 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6599
6600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6601
[email protected]17291a022011-10-10 07:32:536602 HttpServerProperties* http_server_properties =
6603 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116604 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536605 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116606 HostPortPair::FromURL(unrestricted_port_request.url),
6607 kRestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046608 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116609
6610 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416611 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116612
[email protected]49639fa2011-12-20 23:22:416613 int rv = trans->Start(
6614 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116615 EXPECT_EQ(ERR_IO_PENDING, rv);
6616 // Valid change to restricted port should pass.
6617 EXPECT_EQ(OK, callback.WaitForResult());
6618
6619 HttpStreamFactory::set_use_alternate_protocols(false);
6620}
6621
6622TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6623 // Ensure that we're not allowed to redirect traffic via an alternate
6624 // protocol to an unrestricted (port >= 1024) when the original traffic was
6625 // on a restricted port (port < 1024). Ensure that we can redirect in all
6626 // other cases.
6627 HttpStreamFactory::set_use_alternate_protocols(true);
6628 SessionDependencies session_deps;
6629
6630 HttpRequestInfo unrestricted_port_request;
6631 unrestricted_port_request.method = "GET";
6632 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6633 unrestricted_port_request.load_flags = 0;
6634
[email protected]d973e99a2012-02-17 21:02:366635 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116636 StaticSocketDataProvider first_data;
6637 first_data.set_connect_data(mock_connect);
6638 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6639
6640 MockRead data_reads[] = {
6641 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6642 MockRead("hello world"),
6643 MockRead(true, OK),
6644 };
6645 StaticSocketDataProvider second_data(
6646 data_reads, arraysize(data_reads), NULL, 0);
6647 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6648
6649 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6650
[email protected]17291a022011-10-10 07:32:536651 HttpServerProperties* http_server_properties =
6652 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116653 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536654 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116655 HostPortPair::FromURL(unrestricted_port_request.url),
6656 kUnrestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046657 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116658
6659 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416660 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116661
[email protected]49639fa2011-12-20 23:22:416662 int rv = trans->Start(
6663 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116664 EXPECT_EQ(ERR_IO_PENDING, rv);
6665 // Valid change to an unrestricted port should pass.
6666 EXPECT_EQ(OK, callback.WaitForResult());
6667
6668 HttpStreamFactory::set_use_alternate_protocols(false);
6669}
6670
[email protected]eb6234e2012-01-19 01:50:026671TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
6672 // Ensure that we're not allowed to redirect traffic via an alternate
6673 // protocol to an unsafe port, and that we resume the second
6674 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
6675 HttpStreamFactory::set_use_alternate_protocols(true);
6676 SessionDependencies session_deps;
6677
6678 HttpRequestInfo request;
6679 request.method = "GET";
6680 request.url = GURL("http://www.google.com/");
6681 request.load_flags = 0;
6682
6683 // The alternate protocol request will error out before we attempt to connect,
6684 // so only the standard HTTP request will try to connect.
6685 MockRead data_reads[] = {
6686 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6687 MockRead("hello world"),
6688 MockRead(true, OK),
6689 };
6690 StaticSocketDataProvider data(
6691 data_reads, arraysize(data_reads), NULL, 0);
6692 session_deps.socket_factory.AddSocketDataProvider(&data);
6693
6694 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6695
6696 HttpServerProperties* http_server_properties =
6697 session->http_server_properties();
6698 const int kUnsafePort = 7;
6699 http_server_properties->SetAlternateProtocol(
6700 HostPortPair::FromURL(request.url),
6701 kUnsafePort,
6702 NPN_SPDY_2);
6703
6704 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6705 TestCompletionCallback callback;
6706
6707 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6708 EXPECT_EQ(ERR_IO_PENDING, rv);
6709 // The HTTP request should succeed.
6710 EXPECT_EQ(OK, callback.WaitForResult());
6711
6712 // Disable alternate protocol before the asserts.
6713 HttpStreamFactory::set_use_alternate_protocols(false);
6714
6715 const HttpResponseInfo* response = trans->GetResponseInfo();
6716 ASSERT_TRUE(response != NULL);
6717 ASSERT_TRUE(response->headers != NULL);
6718 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6719
6720 std::string response_data;
6721 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6722 EXPECT_EQ("hello world", response_data);
6723}
6724
[email protected]2ff8b312010-04-26 22:20:546725TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386726 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346727 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:546728 SessionDependencies session_deps;
6729
6730 HttpRequestInfo request;
6731 request.method = "GET";
6732 request.url = GURL("http://www.google.com/");
6733 request.load_flags = 0;
6734
6735 MockRead data_reads[] = {
6736 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356737 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546738 MockRead("hello world"),
6739 MockRead(true, OK),
6740 };
6741
6742 StaticSocketDataProvider first_transaction(
6743 data_reads, arraysize(data_reads), NULL, 0);
6744 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6745
6746 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:516747 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2ff8b312010-04-26 22:20:546748 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6749
[email protected]2bd93022010-07-17 00:58:446750 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136751 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546752
[email protected]2bd93022010-07-17 00:58:446753 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6754 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546755 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136756 CreateMockRead(*resp),
6757 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546758 MockRead(true, 0, 0),
6759 };
6760
[email protected]a1595312012-01-22 03:25:046761 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:546762 new DelayedSocketData(
6763 1, // wait for one write to finish before reading.
6764 spdy_reads, arraysize(spdy_reads),
6765 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:046766 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:546767
[email protected]d973e99a2012-02-17 21:02:366768 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:556769 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6770 NULL, 0, NULL, 0);
6771 hanging_non_alternate_protocol_socket.set_connect_data(
6772 never_finishing_connect);
6773 session_deps.socket_factory.AddSocketDataProvider(
6774 &hanging_non_alternate_protocol_socket);
6775
[email protected]49639fa2011-12-20 23:22:416776 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:546777
6778 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6779 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6780
[email protected]49639fa2011-12-20 23:22:416781 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546782 EXPECT_EQ(ERR_IO_PENDING, rv);
6783 EXPECT_EQ(OK, callback.WaitForResult());
6784
6785 const HttpResponseInfo* response = trans->GetResponseInfo();
6786 ASSERT_TRUE(response != NULL);
6787 ASSERT_TRUE(response->headers != NULL);
6788 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6789
6790 std::string response_data;
6791 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6792 EXPECT_EQ("hello world", response_data);
6793
6794 trans.reset(new HttpNetworkTransaction(session));
6795
[email protected]49639fa2011-12-20 23:22:416796 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546797 EXPECT_EQ(ERR_IO_PENDING, rv);
6798 EXPECT_EQ(OK, callback.WaitForResult());
6799
6800 response = trans->GetResponseInfo();
6801 ASSERT_TRUE(response != NULL);
6802 ASSERT_TRUE(response->headers != NULL);
6803 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536804 EXPECT_TRUE(response->was_fetched_via_spdy);
6805 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546806
6807 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6808 EXPECT_EQ("hello!", response_data);
6809
[email protected]5285d972011-10-18 18:56:346810 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:386811 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546812}
6813
[email protected]2d6728692011-03-12 01:39:556814TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6815 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346816 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556817 SessionDependencies session_deps;
6818
6819 HttpRequestInfo request;
6820 request.method = "GET";
6821 request.url = GURL("http://www.google.com/");
6822 request.load_flags = 0;
6823
6824 MockRead data_reads[] = {
6825 MockRead("HTTP/1.1 200 OK\r\n"),
6826 MockRead(kAlternateProtocolHttpHeader),
6827 MockRead("hello world"),
6828 MockRead(true, OK),
6829 };
6830
6831 StaticSocketDataProvider first_transaction(
6832 data_reads, arraysize(data_reads), NULL, 0);
6833 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6834 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6835
[email protected]d973e99a2012-02-17 21:02:366836 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:556837 StaticSocketDataProvider hanging_socket(
6838 NULL, 0, NULL, 0);
6839 hanging_socket.set_connect_data(never_finishing_connect);
6840 // Socket 2 and 3 are the hanging Alternate-Protocol and
6841 // non-Alternate-Protocol jobs from the 2nd transaction.
6842 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6843 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6844
6845 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:516846 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2d6728692011-03-12 01:39:556847 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6848
6849 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6850 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6851 MockWrite spdy_writes[] = {
6852 CreateMockWrite(*req1),
6853 CreateMockWrite(*req2),
6854 };
6855 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6856 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6857 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6858 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6859 MockRead spdy_reads[] = {
6860 CreateMockRead(*resp1),
6861 CreateMockRead(*data1),
6862 CreateMockRead(*resp2),
6863 CreateMockRead(*data2),
6864 MockRead(true, 0, 0),
6865 };
6866
[email protected]a1595312012-01-22 03:25:046867 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2d6728692011-03-12 01:39:556868 new DelayedSocketData(
6869 2, // wait for writes to finish before reading.
6870 spdy_reads, arraysize(spdy_reads),
6871 spdy_writes, arraysize(spdy_writes)));
6872 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]a1595312012-01-22 03:25:046873 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2d6728692011-03-12 01:39:556874
6875 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6876 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6877
6878 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]49639fa2011-12-20 23:22:416879 TestCompletionCallback callback1;
[email protected]2d6728692011-03-12 01:39:556880 HttpNetworkTransaction trans1(session);
6881
[email protected]49639fa2011-12-20 23:22:416882 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556883 EXPECT_EQ(ERR_IO_PENDING, rv);
6884 EXPECT_EQ(OK, callback1.WaitForResult());
6885
6886 const HttpResponseInfo* response = trans1.GetResponseInfo();
6887 ASSERT_TRUE(response != NULL);
6888 ASSERT_TRUE(response->headers != NULL);
6889 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6890
6891 std::string response_data;
6892 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6893 EXPECT_EQ("hello world", response_data);
6894
[email protected]49639fa2011-12-20 23:22:416895 TestCompletionCallback callback2;
[email protected]2d6728692011-03-12 01:39:556896 HttpNetworkTransaction trans2(session);
[email protected]49639fa2011-12-20 23:22:416897 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556898 EXPECT_EQ(ERR_IO_PENDING, rv);
6899
[email protected]49639fa2011-12-20 23:22:416900 TestCompletionCallback callback3;
[email protected]2d6728692011-03-12 01:39:556901 HttpNetworkTransaction trans3(session);
[email protected]49639fa2011-12-20 23:22:416902 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556903 EXPECT_EQ(ERR_IO_PENDING, rv);
6904
6905 EXPECT_EQ(OK, callback2.WaitForResult());
6906 EXPECT_EQ(OK, callback3.WaitForResult());
6907
6908 response = trans2.GetResponseInfo();
6909 ASSERT_TRUE(response != NULL);
6910 ASSERT_TRUE(response->headers != NULL);
6911 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6912 EXPECT_TRUE(response->was_fetched_via_spdy);
6913 EXPECT_TRUE(response->was_npn_negotiated);
6914 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6915 EXPECT_EQ("hello!", response_data);
6916
6917 response = trans3.GetResponseInfo();
6918 ASSERT_TRUE(response != NULL);
6919 ASSERT_TRUE(response->headers != NULL);
6920 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6921 EXPECT_TRUE(response->was_fetched_via_spdy);
6922 EXPECT_TRUE(response->was_npn_negotiated);
6923 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6924 EXPECT_EQ("hello!", response_data);
6925
[email protected]5285d972011-10-18 18:56:346926 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:556927 HttpStreamFactory::set_use_alternate_protocols(false);
6928}
6929
6930TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6931 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346932 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556933 SessionDependencies session_deps;
6934
6935 HttpRequestInfo request;
6936 request.method = "GET";
6937 request.url = GURL("http://www.google.com/");
6938 request.load_flags = 0;
6939
6940 MockRead data_reads[] = {
6941 MockRead("HTTP/1.1 200 OK\r\n"),
6942 MockRead(kAlternateProtocolHttpHeader),
6943 MockRead("hello world"),
6944 MockRead(true, OK),
6945 };
6946
6947 StaticSocketDataProvider first_transaction(
6948 data_reads, arraysize(data_reads), NULL, 0);
6949 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6950
6951 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:516952 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2d6728692011-03-12 01:39:556953 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6954
[email protected]d973e99a2012-02-17 21:02:366955 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:556956 StaticSocketDataProvider hanging_alternate_protocol_socket(
6957 NULL, 0, NULL, 0);
6958 hanging_alternate_protocol_socket.set_connect_data(
6959 never_finishing_connect);
6960 session_deps.socket_factory.AddSocketDataProvider(
6961 &hanging_alternate_protocol_socket);
6962
6963 // 2nd request is just a copy of the first one, over HTTP again.
6964 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6965
[email protected]49639fa2011-12-20 23:22:416966 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:556967
6968 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6969 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6970
[email protected]49639fa2011-12-20 23:22:416971 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556972 EXPECT_EQ(ERR_IO_PENDING, rv);
6973 EXPECT_EQ(OK, callback.WaitForResult());
6974
6975 const HttpResponseInfo* response = trans->GetResponseInfo();
6976 ASSERT_TRUE(response != NULL);
6977 ASSERT_TRUE(response->headers != NULL);
6978 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6979
6980 std::string response_data;
6981 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6982 EXPECT_EQ("hello world", response_data);
6983
6984 trans.reset(new HttpNetworkTransaction(session));
6985
[email protected]49639fa2011-12-20 23:22:416986 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556987 EXPECT_EQ(ERR_IO_PENDING, rv);
6988 EXPECT_EQ(OK, callback.WaitForResult());
6989
6990 response = trans->GetResponseInfo();
6991 ASSERT_TRUE(response != NULL);
6992 ASSERT_TRUE(response->headers != NULL);
6993 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6994 EXPECT_FALSE(response->was_fetched_via_spdy);
6995 EXPECT_FALSE(response->was_npn_negotiated);
6996
6997 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6998 EXPECT_EQ("hello world", response_data);
6999
[email protected]5285d972011-10-18 18:56:347000 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557001 HttpStreamFactory::set_use_alternate_protocols(false);
7002}
7003
[email protected]631f1322010-04-30 17:59:117004class CapturingProxyResolver : public ProxyResolver {
7005 public:
7006 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7007 virtual ~CapturingProxyResolver() {}
7008
7009 virtual int GetProxyForURL(const GURL& url,
7010 ProxyInfo* results,
[email protected]235786812011-12-20 02:15:317011 const CompletionCallback& callback,
[email protected]631f1322010-04-30 17:59:117012 RequestHandle* request,
7013 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:407014 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7015 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:427016 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:117017 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:427018 return OK;
[email protected]631f1322010-04-30 17:59:117019 }
7020
7021 virtual void CancelRequest(RequestHandle request) {
7022 NOTREACHED();
7023 }
7024
[email protected]f2c971f2011-11-08 00:33:177025 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
7026 NOTREACHED();
7027 return LOAD_STATE_IDLE;
7028 }
7029
7030 virtual LoadState GetLoadStateThreadSafe(
7031 RequestHandle request) const OVERRIDE {
7032 NOTREACHED();
7033 return LOAD_STATE_IDLE;
7034 }
7035
[email protected]1e605472010-12-16 21:41:407036 virtual void CancelSetPacScript() {
7037 NOTREACHED();
7038 }
7039
[email protected]24476402010-07-20 20:55:177040 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]235786812011-12-20 02:15:317041 const CompletionCallback& /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:427042 return OK;
[email protected]631f1322010-04-30 17:59:117043 }
7044
[email protected]24476402010-07-20 20:55:177045 const std::vector<GURL>& resolved() const { return resolved_; }
7046
7047 private:
[email protected]631f1322010-04-30 17:59:117048 std::vector<GURL> resolved_;
7049
7050 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7051};
7052
[email protected]631f1322010-04-30 17:59:117053TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:387054 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347055 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]631f1322010-04-30 17:59:117056
7057 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:427058 proxy_config.set_auto_detect(true);
7059 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:117060
[email protected]631f1322010-04-30 17:59:117061 CapturingProxyResolver* capturing_proxy_resolver =
7062 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:387063 SessionDependencies session_deps(new ProxyService(
7064 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7065 NULL));
[email protected]631f1322010-04-30 17:59:117066
7067 HttpRequestInfo request;
7068 request.method = "GET";
7069 request.url = GURL("http://www.google.com/");
7070 request.load_flags = 0;
7071
7072 MockRead data_reads[] = {
7073 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357074 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:117075 MockRead("hello world"),
7076 MockRead(true, OK),
7077 };
7078
7079 StaticSocketDataProvider first_transaction(
7080 data_reads, arraysize(data_reads), NULL, 0);
7081 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7082
7083 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:517084 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]631f1322010-04-30 17:59:117085 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7086
[email protected]2bd93022010-07-17 00:58:447087 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:117088 MockWrite spdy_writes[] = {
7089 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7090 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:427091 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:137092 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:117093 };
7094
[email protected]d911f1b2010-05-05 22:39:427095 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7096
[email protected]2bd93022010-07-17 00:58:447097 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7098 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:117099 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:427100 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:137101 CreateMockRead(*resp.get(), 4), // 2, 4
7102 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:427103 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:117104 };
7105
[email protected]a1595312012-01-22 03:25:047106 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d911f1b2010-05-05 22:39:427107 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:117108 spdy_reads, arraysize(spdy_reads),
7109 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047110 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]631f1322010-04-30 17:59:117111
[email protected]d973e99a2012-02-17 21:02:367112 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:557113 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7114 NULL, 0, NULL, 0);
7115 hanging_non_alternate_protocol_socket.set_connect_data(
7116 never_finishing_connect);
7117 session_deps.socket_factory.AddSocketDataProvider(
7118 &hanging_non_alternate_protocol_socket);
7119
[email protected]49639fa2011-12-20 23:22:417120 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:117121
7122 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7123 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7124
[email protected]49639fa2011-12-20 23:22:417125 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117126 EXPECT_EQ(ERR_IO_PENDING, rv);
7127 EXPECT_EQ(OK, callback.WaitForResult());
7128
7129 const HttpResponseInfo* response = trans->GetResponseInfo();
7130 ASSERT_TRUE(response != NULL);
7131 ASSERT_TRUE(response->headers != NULL);
7132 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537133 EXPECT_FALSE(response->was_fetched_via_spdy);
7134 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117135
7136 std::string response_data;
7137 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7138 EXPECT_EQ("hello world", response_data);
7139
7140 trans.reset(new HttpNetworkTransaction(session));
7141
[email protected]49639fa2011-12-20 23:22:417142 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117143 EXPECT_EQ(ERR_IO_PENDING, rv);
7144 EXPECT_EQ(OK, callback.WaitForResult());
7145
7146 response = trans->GetResponseInfo();
7147 ASSERT_TRUE(response != NULL);
7148 ASSERT_TRUE(response->headers != NULL);
7149 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537150 EXPECT_TRUE(response->was_fetched_via_spdy);
7151 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117152
7153 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7154 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557155 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427156 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117157 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427158 EXPECT_EQ("https://www.google.com/",
7159 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117160
[email protected]5285d972011-10-18 18:56:347161 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387162 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117163}
[email protected]631f1322010-04-30 17:59:117164
[email protected]2ff8b312010-04-26 22:20:547165TEST_F(HttpNetworkTransactionTest,
7166 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387167 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347168 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:547169 SessionDependencies session_deps;
7170
7171 HttpRequestInfo request;
7172 request.method = "GET";
7173 request.url = GURL("http://www.google.com/");
7174 request.load_flags = 0;
7175
7176 MockRead data_reads[] = {
7177 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357178 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547179 MockRead("hello world"),
7180 MockRead(true, OK),
7181 };
7182
7183 StaticSocketDataProvider first_transaction(
7184 data_reads, arraysize(data_reads), NULL, 0);
7185 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7186
7187 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:517188 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2ff8b312010-04-26 22:20:547189 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537190 // Make sure we use ssl for spdy here.
7191 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547192
[email protected]2bd93022010-07-17 00:58:447193 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137194 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547195
[email protected]2bd93022010-07-17 00:58:447196 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7197 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547198 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137199 CreateMockRead(*resp),
7200 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547201 MockRead(true, 0, 0),
7202 };
7203
[email protected]a1595312012-01-22 03:25:047204 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:547205 new DelayedSocketData(
7206 1, // wait for one write to finish before reading.
7207 spdy_reads, arraysize(spdy_reads),
7208 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047209 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:547210
[email protected]83039bb2011-12-09 18:43:557211 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:547212
7213 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7214
7215 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7216
[email protected]49639fa2011-12-20 23:22:417217 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547218 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417219 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547220
7221 const HttpResponseInfo* response = trans->GetResponseInfo();
7222 ASSERT_TRUE(response != NULL);
7223 ASSERT_TRUE(response->headers != NULL);
7224 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7225
7226 std::string response_data;
7227 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7228 EXPECT_EQ("hello world", response_data);
7229
7230 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387231 HostPortPair host_port_pair("www.google.com", 443);
7232 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547233 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317234 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287235 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:297236 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]02b0c342010-09-25 21:09:387237
7238 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7239 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287240 connection->Init(host_port_pair.ToString(),
7241 transport_params,
7242 LOWEST,
[email protected]6ecf2b92011-12-15 01:14:527243 callback.callback(),
[email protected]a42dbd142011-11-17 16:42:027244 session->GetTransportSocketPool(),
[email protected]02b0c342010-09-25 21:09:387245 BoundNetLog()));
[email protected]6ecf2b92011-12-15 01:14:527246 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]02b0c342010-09-25 21:09:387247
7248 SSLConfig ssl_config;
7249 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347250 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177251 SSLClientSocketContext context;
7252 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347253 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7254 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177255 NULL /* ssl_host_info */, context));
[email protected]83039bb2011-12-09 18:43:557256 EXPECT_EQ(ERR_IO_PENDING,
7257 ssl_connection->socket()->Connect(callback.callback()));
[email protected]02b0c342010-09-25 21:09:387258 EXPECT_EQ(OK, callback.WaitForResult());
7259
[email protected]9e1bdd32011-02-03 21:48:347260 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387261 true, OK));
7262
[email protected]2ff8b312010-04-26 22:20:547263 trans.reset(new HttpNetworkTransaction(session));
7264
[email protected]49639fa2011-12-20 23:22:417265 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547266 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417267 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547268
7269 response = trans->GetResponseInfo();
7270 ASSERT_TRUE(response != NULL);
7271 ASSERT_TRUE(response->headers != NULL);
7272 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537273 EXPECT_TRUE(response->was_fetched_via_spdy);
7274 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547275
7276 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7277 EXPECT_EQ("hello!", response_data);
7278
[email protected]5285d972011-10-18 18:56:347279 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387280 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427281}
7282
[email protected]044de0642010-06-17 10:42:157283// GenerateAuthToken is a mighty big test.
7284// It tests all permutation of GenerateAuthToken behavior:
7285// - Synchronous and Asynchronous completion.
7286// - OK or error on completion.
7287// - Direct connection, non-authenticating proxy, and authenticating proxy.
7288// - HTTP or HTTPS backend (to include proxy tunneling).
7289// - Non-authenticating and authenticating backend.
7290//
[email protected]fe3b7dc2012-02-03 19:52:097291// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:157292// problems generating an auth token for an authenticating proxy, we don't
7293// need to test all permutations of the backend server).
7294//
7295// The test proceeds by going over each of the configuration cases, and
7296// potentially running up to three rounds in each of the tests. The TestConfig
7297// specifies both the configuration for the test as well as the expectations
7298// for the results.
7299TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507300 static const char kServer[] = "http://www.example.com";
7301 static const char kSecureServer[] = "https://www.example.com";
7302 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157303 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7304
7305 enum AuthTiming {
7306 AUTH_NONE,
7307 AUTH_SYNC,
7308 AUTH_ASYNC,
7309 };
7310
7311 const MockWrite kGet(
7312 "GET / HTTP/1.1\r\n"
7313 "Host: www.example.com\r\n"
7314 "Connection: keep-alive\r\n\r\n");
7315 const MockWrite kGetProxy(
7316 "GET http://www.example.com/ HTTP/1.1\r\n"
7317 "Host: www.example.com\r\n"
7318 "Proxy-Connection: keep-alive\r\n\r\n");
7319 const MockWrite kGetAuth(
7320 "GET / HTTP/1.1\r\n"
7321 "Host: www.example.com\r\n"
7322 "Connection: keep-alive\r\n"
7323 "Authorization: auth_token\r\n\r\n");
7324 const MockWrite kGetProxyAuth(
7325 "GET http://www.example.com/ HTTP/1.1\r\n"
7326 "Host: www.example.com\r\n"
7327 "Proxy-Connection: keep-alive\r\n"
7328 "Proxy-Authorization: auth_token\r\n\r\n");
7329 const MockWrite kGetAuthThroughProxy(
7330 "GET http://www.example.com/ HTTP/1.1\r\n"
7331 "Host: www.example.com\r\n"
7332 "Proxy-Connection: keep-alive\r\n"
7333 "Authorization: auth_token\r\n\r\n");
7334 const MockWrite kGetAuthWithProxyAuth(
7335 "GET http://www.example.com/ HTTP/1.1\r\n"
7336 "Host: www.example.com\r\n"
7337 "Proxy-Connection: keep-alive\r\n"
7338 "Proxy-Authorization: auth_token\r\n"
7339 "Authorization: auth_token\r\n\r\n");
7340 const MockWrite kConnect(
7341 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7342 "Host: www.example.com\r\n"
7343 "Proxy-Connection: keep-alive\r\n\r\n");
7344 const MockWrite kConnectProxyAuth(
7345 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7346 "Host: www.example.com\r\n"
7347 "Proxy-Connection: keep-alive\r\n"
7348 "Proxy-Authorization: auth_token\r\n\r\n");
7349
7350 const MockRead kSuccess(
7351 "HTTP/1.1 200 OK\r\n"
7352 "Content-Type: text/html; charset=iso-8859-1\r\n"
7353 "Content-Length: 3\r\n\r\n"
7354 "Yes");
7355 const MockRead kFailure(
7356 "Should not be called.");
7357 const MockRead kServerChallenge(
7358 "HTTP/1.1 401 Unauthorized\r\n"
7359 "WWW-Authenticate: Mock realm=server\r\n"
7360 "Content-Type: text/html; charset=iso-8859-1\r\n"
7361 "Content-Length: 14\r\n\r\n"
7362 "Unauthorized\r\n");
7363 const MockRead kProxyChallenge(
7364 "HTTP/1.1 407 Unauthorized\r\n"
7365 "Proxy-Authenticate: Mock realm=proxy\r\n"
7366 "Proxy-Connection: close\r\n"
7367 "Content-Type: text/html; charset=iso-8859-1\r\n"
7368 "Content-Length: 14\r\n\r\n"
7369 "Unauthorized\r\n");
7370 const MockRead kProxyConnected(
7371 "HTTP/1.1 200 Connection Established\r\n\r\n");
7372
7373 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7374 // no constructors, but the C++ compiler on Windows warns about
7375 // unspecified data in compound literals. So, moved to using constructors,
7376 // and TestRound's created with the default constructor should not be used.
7377 struct TestRound {
7378 TestRound()
7379 : expected_rv(ERR_UNEXPECTED),
7380 extra_write(NULL),
7381 extra_read(NULL) {
7382 }
7383 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7384 int expected_rv_arg)
7385 : write(write_arg),
7386 read(read_arg),
7387 expected_rv(expected_rv_arg),
7388 extra_write(NULL),
7389 extra_read(NULL) {
7390 }
7391 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7392 int expected_rv_arg, const MockWrite* extra_write_arg,
7393 const MockWrite* extra_read_arg)
7394 : write(write_arg),
7395 read(read_arg),
7396 expected_rv(expected_rv_arg),
7397 extra_write(extra_write_arg),
7398 extra_read(extra_read_arg) {
7399 }
7400 MockWrite write;
7401 MockRead read;
7402 int expected_rv;
7403 const MockWrite* extra_write;
7404 const MockRead* extra_read;
7405 };
7406
7407 static const int kNoSSL = 500;
7408
7409 struct TestConfig {
7410 const char* proxy_url;
7411 AuthTiming proxy_auth_timing;
7412 int proxy_auth_rv;
7413 const char* server_url;
7414 AuthTiming server_auth_timing;
7415 int server_auth_rv;
7416 int num_auth_rounds;
7417 int first_ssl_round;
7418 TestRound rounds[3];
7419 } test_configs[] = {
7420 // Non-authenticating HTTP server with a direct connection.
7421 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7422 { TestRound(kGet, kSuccess, OK)}},
7423 // Authenticating HTTP server with a direct connection.
7424 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7425 { TestRound(kGet, kServerChallenge, OK),
7426 TestRound(kGetAuth, kSuccess, OK)}},
7427 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7428 { TestRound(kGet, kServerChallenge, OK),
7429 TestRound(kGetAuth, kFailure, kAuthErr)}},
7430 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7431 { TestRound(kGet, kServerChallenge, OK),
7432 TestRound(kGetAuth, kSuccess, OK)}},
7433 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7434 { TestRound(kGet, kServerChallenge, OK),
7435 TestRound(kGetAuth, kFailure, kAuthErr)}},
7436 // Non-authenticating HTTP server through a non-authenticating proxy.
7437 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7438 { TestRound(kGetProxy, kSuccess, OK)}},
7439 // Authenticating HTTP server through a non-authenticating proxy.
7440 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7441 { TestRound(kGetProxy, kServerChallenge, OK),
7442 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7443 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7444 { TestRound(kGetProxy, kServerChallenge, OK),
7445 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7446 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7447 { TestRound(kGetProxy, kServerChallenge, OK),
7448 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7449 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7450 { TestRound(kGetProxy, kServerChallenge, OK),
7451 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7452 // Non-authenticating HTTP server through an authenticating proxy.
7453 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7454 { TestRound(kGetProxy, kProxyChallenge, OK),
7455 TestRound(kGetProxyAuth, kSuccess, OK)}},
7456 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7457 { TestRound(kGetProxy, kProxyChallenge, OK),
7458 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7459 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7460 { TestRound(kGetProxy, kProxyChallenge, OK),
7461 TestRound(kGetProxyAuth, kSuccess, OK)}},
7462 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7463 { TestRound(kGetProxy, kProxyChallenge, OK),
7464 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7465 // Authenticating HTTP server through an authenticating proxy.
7466 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7467 { TestRound(kGetProxy, kProxyChallenge, OK),
7468 TestRound(kGetProxyAuth, kServerChallenge, OK),
7469 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7470 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7471 { TestRound(kGetProxy, kProxyChallenge, OK),
7472 TestRound(kGetProxyAuth, kServerChallenge, OK),
7473 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7474 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7475 { TestRound(kGetProxy, kProxyChallenge, OK),
7476 TestRound(kGetProxyAuth, kServerChallenge, OK),
7477 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7478 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7479 { TestRound(kGetProxy, kProxyChallenge, OK),
7480 TestRound(kGetProxyAuth, kServerChallenge, OK),
7481 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7482 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7483 { TestRound(kGetProxy, kProxyChallenge, OK),
7484 TestRound(kGetProxyAuth, kServerChallenge, OK),
7485 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7486 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7487 { TestRound(kGetProxy, kProxyChallenge, OK),
7488 TestRound(kGetProxyAuth, kServerChallenge, OK),
7489 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7490 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7491 { TestRound(kGetProxy, kProxyChallenge, OK),
7492 TestRound(kGetProxyAuth, kServerChallenge, OK),
7493 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7494 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7495 { TestRound(kGetProxy, kProxyChallenge, OK),
7496 TestRound(kGetProxyAuth, kServerChallenge, OK),
7497 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7498 // Non-authenticating HTTPS server with a direct connection.
7499 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7500 { TestRound(kGet, kSuccess, OK)}},
7501 // Authenticating HTTPS server with a direct connection.
7502 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7503 { TestRound(kGet, kServerChallenge, OK),
7504 TestRound(kGetAuth, kSuccess, OK)}},
7505 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7506 { TestRound(kGet, kServerChallenge, OK),
7507 TestRound(kGetAuth, kFailure, kAuthErr)}},
7508 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7509 { TestRound(kGet, kServerChallenge, OK),
7510 TestRound(kGetAuth, kSuccess, OK)}},
7511 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7512 { TestRound(kGet, kServerChallenge, OK),
7513 TestRound(kGetAuth, kFailure, kAuthErr)}},
7514 // Non-authenticating HTTPS server with a non-authenticating proxy.
7515 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7516 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7517 // Authenticating HTTPS server through a non-authenticating proxy.
7518 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7519 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7520 TestRound(kGetAuth, kSuccess, OK)}},
7521 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7522 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7523 TestRound(kGetAuth, kFailure, kAuthErr)}},
7524 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7525 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7526 TestRound(kGetAuth, kSuccess, OK)}},
7527 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7528 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7529 TestRound(kGetAuth, kFailure, kAuthErr)}},
7530 // Non-Authenticating HTTPS server through an authenticating proxy.
7531 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7532 { TestRound(kConnect, kProxyChallenge, OK),
7533 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7534 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7535 { TestRound(kConnect, kProxyChallenge, OK),
7536 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7537 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7538 { TestRound(kConnect, kProxyChallenge, OK),
7539 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7540 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7541 { TestRound(kConnect, kProxyChallenge, OK),
7542 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7543 // Authenticating HTTPS server through an authenticating proxy.
7544 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7545 { TestRound(kConnect, kProxyChallenge, OK),
7546 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7547 &kGet, &kServerChallenge),
7548 TestRound(kGetAuth, kSuccess, OK)}},
7549 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7550 { TestRound(kConnect, kProxyChallenge, OK),
7551 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7552 &kGet, &kServerChallenge),
7553 TestRound(kGetAuth, kFailure, kAuthErr)}},
7554 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7555 { TestRound(kConnect, kProxyChallenge, OK),
7556 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7557 &kGet, &kServerChallenge),
7558 TestRound(kGetAuth, kSuccess, OK)}},
7559 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7560 { TestRound(kConnect, kProxyChallenge, OK),
7561 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7562 &kGet, &kServerChallenge),
7563 TestRound(kGetAuth, kFailure, kAuthErr)}},
7564 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7565 { TestRound(kConnect, kProxyChallenge, OK),
7566 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7567 &kGet, &kServerChallenge),
7568 TestRound(kGetAuth, kSuccess, OK)}},
7569 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7570 { TestRound(kConnect, kProxyChallenge, OK),
7571 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7572 &kGet, &kServerChallenge),
7573 TestRound(kGetAuth, kFailure, kAuthErr)}},
7574 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7575 { TestRound(kConnect, kProxyChallenge, OK),
7576 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7577 &kGet, &kServerChallenge),
7578 TestRound(kGetAuth, kSuccess, OK)}},
7579 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7580 { TestRound(kConnect, kProxyChallenge, OK),
7581 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7582 &kGet, &kServerChallenge),
7583 TestRound(kGetAuth, kFailure, kAuthErr)}},
7584 };
7585
7586 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157587 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087588 HttpAuthHandlerMock::Factory* auth_factory(
7589 new HttpAuthHandlerMock::Factory());
7590 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157591 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267592
7593 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157594 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087595 for (int n = 0; n < 2; n++) {
7596 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7597 std::string auth_challenge = "Mock realm=proxy";
7598 GURL origin(test_config.proxy_url);
7599 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7600 auth_challenge.end());
7601 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7602 origin, BoundNetLog());
7603 auth_handler->SetGenerateExpectation(
7604 test_config.proxy_auth_timing == AUTH_ASYNC,
7605 test_config.proxy_auth_rv);
7606 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7607 }
[email protected]044de0642010-06-17 10:42:157608 }
7609 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007610 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157611 std::string auth_challenge = "Mock realm=server";
7612 GURL origin(test_config.server_url);
7613 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7614 auth_challenge.end());
7615 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7616 origin, BoundNetLog());
7617 auth_handler->SetGenerateExpectation(
7618 test_config.server_auth_timing == AUTH_ASYNC,
7619 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087620 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157621 }
7622 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127623 session_deps.proxy_service.reset(
7624 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157625 } else {
[email protected]6104ea5d2011-04-27 21:37:127626 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157627 }
7628
7629 HttpRequestInfo request;
7630 request.method = "GET";
7631 request.url = GURL(test_config.server_url);
7632 request.load_flags = 0;
7633
[email protected]0b0bf032010-09-21 18:08:507634 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7635 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157636
7637 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7638 const TestRound& read_write_round = test_config.rounds[round];
7639
7640 // Set up expected reads and writes.
7641 MockRead reads[2];
7642 reads[0] = read_write_round.read;
7643 size_t length_reads = 1;
7644 if (read_write_round.extra_read) {
7645 reads[1] = *read_write_round.extra_read;
7646 length_reads = 2;
7647 }
7648
7649 MockWrite writes[2];
7650 writes[0] = read_write_round.write;
7651 size_t length_writes = 1;
7652 if (read_write_round.extra_write) {
7653 writes[1] = *read_write_round.extra_write;
7654 length_writes = 2;
7655 }
7656 StaticSocketDataProvider data_provider(
7657 reads, length_reads, writes, length_writes);
7658 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7659
7660 // Add an SSL sequence if necessary.
7661 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7662 if (round >= test_config.first_ssl_round)
7663 session_deps.socket_factory.AddSSLSocketDataProvider(
7664 &ssl_socket_data_provider);
7665
7666 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:417667 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:157668 int rv;
7669 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:417670 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:157671 } else {
[email protected]49639fa2011-12-20 23:22:417672 rv = trans.RestartWithAuth(
7673 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:157674 }
7675 if (rv == ERR_IO_PENDING)
7676 rv = callback.WaitForResult();
7677
7678 // Compare results with expected data.
7679 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507680 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157681 if (read_write_round.expected_rv == OK) {
[email protected]fe2255a2011-09-20 19:37:507682 ASSERT_TRUE(response != NULL);
[email protected]044de0642010-06-17 10:42:157683 } else {
7684 EXPECT_TRUE(response == NULL);
7685 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7686 continue;
7687 }
7688 if (round + 1 < test_config.num_auth_rounds) {
7689 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7690 } else {
7691 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7692 }
7693 }
[email protected]e5ae96a2010-04-14 20:12:457694 }
7695}
7696
[email protected]c871bce92010-07-15 21:51:147697TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7698 // Do multi-round authentication and make sure it works correctly.
7699 SessionDependencies session_deps;
7700 HttpAuthHandlerMock::Factory* auth_factory(
7701 new HttpAuthHandlerMock::Factory());
7702 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127703 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147704 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7705 session_deps.host_resolver->set_synchronous_mode(true);
7706
7707 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7708 auth_handler->set_connection_based(true);
7709 std::string auth_challenge = "Mock realm=server";
7710 GURL origin("http://www.example.com");
7711 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7712 auth_challenge.end());
7713 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7714 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087715 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147716
[email protected]c871bce92010-07-15 21:51:147717 int rv = OK;
7718 const HttpResponseInfo* response = NULL;
7719 HttpRequestInfo request;
7720 request.method = "GET";
7721 request.url = origin;
7722 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277723
7724 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107725
7726 // Use a TCP Socket Pool with only one connection per group. This is used
7727 // to validate that the TCP socket is not released to the pool between
7728 // each round of multi-round authentication.
7729 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287730 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7731 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107732 50, // Max sockets for pool
7733 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287734 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107735 session_deps.host_resolver.get(),
7736 &session_deps.socket_factory,
7737 session_deps.net_log);
[email protected]a42dbd142011-11-17 16:42:027738 MockClientSocketPoolManager* mock_pool_manager =
7739 new MockClientSocketPoolManager;
7740 mock_pool_manager->SetTransportSocketPool(transport_pool);
7741 session_peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]7ef4cbbb2011-02-06 11:19:107742
[email protected]cb9bf6ca2011-01-28 13:15:277743 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417744 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:147745
7746 const MockWrite kGet(
7747 "GET / HTTP/1.1\r\n"
7748 "Host: www.example.com\r\n"
7749 "Connection: keep-alive\r\n\r\n");
7750 const MockWrite kGetAuth(
7751 "GET / HTTP/1.1\r\n"
7752 "Host: www.example.com\r\n"
7753 "Connection: keep-alive\r\n"
7754 "Authorization: auth_token\r\n\r\n");
7755
7756 const MockRead kServerChallenge(
7757 "HTTP/1.1 401 Unauthorized\r\n"
7758 "WWW-Authenticate: Mock realm=server\r\n"
7759 "Content-Type: text/html; charset=iso-8859-1\r\n"
7760 "Content-Length: 14\r\n\r\n"
7761 "Unauthorized\r\n");
7762 const MockRead kSuccess(
7763 "HTTP/1.1 200 OK\r\n"
7764 "Content-Type: text/html; charset=iso-8859-1\r\n"
7765 "Content-Length: 3\r\n\r\n"
7766 "Yes");
7767
7768 MockWrite writes[] = {
7769 // First round
7770 kGet,
7771 // Second round
7772 kGetAuth,
7773 // Third round
7774 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307775 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107776 kGetAuth,
7777 // Competing request
7778 kGet,
[email protected]c871bce92010-07-15 21:51:147779 };
7780 MockRead reads[] = {
7781 // First round
7782 kServerChallenge,
7783 // Second round
7784 kServerChallenge,
7785 // Third round
[email protected]eca50e122010-09-11 14:03:307786 kServerChallenge,
7787 // Fourth round
[email protected]c871bce92010-07-15 21:51:147788 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107789 // Competing response
7790 kSuccess,
[email protected]c871bce92010-07-15 21:51:147791 };
7792 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7793 writes, arraysize(writes));
7794 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7795
[email protected]7ef4cbbb2011-02-06 11:19:107796 const char* const kSocketGroup = "www.example.com:80";
7797
7798 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147799 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417800 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:147801 if (rv == ERR_IO_PENDING)
7802 rv = callback.WaitForResult();
7803 EXPECT_EQ(OK, rv);
7804 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507805 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147806 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287807 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147808
[email protected]7ef4cbbb2011-02-06 11:19:107809 // In between rounds, another request comes in for the same domain.
7810 // It should not be able to grab the TCP socket that trans has already
7811 // claimed.
7812 scoped_ptr<HttpTransaction> trans_compete(
7813 new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417814 TestCompletionCallback callback_compete;
7815 rv = trans_compete->Start(
7816 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:107817 EXPECT_EQ(ERR_IO_PENDING, rv);
7818 // callback_compete.WaitForResult at this point would stall forever,
7819 // since the HttpNetworkTransaction does not release the request back to
7820 // the pool until after authentication completes.
7821
7822 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147823 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417824 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:147825 if (rv == ERR_IO_PENDING)
7826 rv = callback.WaitForResult();
7827 EXPECT_EQ(OK, rv);
7828 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507829 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147830 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287831 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147832
[email protected]7ef4cbbb2011-02-06 11:19:107833 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147834 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417835 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:147836 if (rv == ERR_IO_PENDING)
7837 rv = callback.WaitForResult();
7838 EXPECT_EQ(OK, rv);
7839 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507840 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147841 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287842 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307843
[email protected]7ef4cbbb2011-02-06 11:19:107844 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307845 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417846 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:307847 if (rv == ERR_IO_PENDING)
7848 rv = callback.WaitForResult();
7849 EXPECT_EQ(OK, rv);
7850 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507851 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:307852 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287853 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107854
7855 // Read the body since the fourth round was successful. This will also
7856 // release the socket back to the pool.
7857 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]49639fa2011-12-20 23:22:417858 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107859 if (rv == ERR_IO_PENDING)
7860 rv = callback.WaitForResult();
7861 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:417862 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107863 EXPECT_EQ(0, rv);
7864 // There are still 0 idle sockets, since the trans_compete transaction
7865 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287866 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107867
7868 // The competing request can now finish. Wait for the headers and then
7869 // read the body.
7870 rv = callback_compete.WaitForResult();
7871 EXPECT_EQ(OK, rv);
[email protected]49639fa2011-12-20 23:22:417872 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107873 if (rv == ERR_IO_PENDING)
7874 rv = callback.WaitForResult();
7875 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:417876 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107877 EXPECT_EQ(0, rv);
7878
7879 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287880 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147881}
7882
[email protected]aeaca1f2010-04-20 22:05:217883class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7884 public:
[email protected]06650c52010-06-03 00:49:177885 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217886 : fail_all_(fail_all) {
7887 }
7888
7889 virtual MockRead GetNextRead() {
7890 if (fail_all_)
7891 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7892
7893 return MockRead(false /* async */,
7894 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7895 }
7896
7897 virtual MockWriteResult OnWrite(const std::string& data) {
7898 return MockWriteResult(false /* async */, data.size());
7899 }
7900
7901 void Reset() {
7902 }
7903
7904 private:
7905 const bool fail_all_;
7906};
7907
7908// Test that we restart a connection when we see a decompression failure from
7909// the peer during the handshake. (In the real world we'll restart with SSLv3
7910// and we won't offer DEFLATE in that case.)
7911TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7912 HttpRequestInfo request;
7913 request.method = "GET";
7914 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7915 request.load_flags = 0;
7916
7917 SessionDependencies session_deps;
7918 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7919 false /* fail all reads */);
7920 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7921 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117922 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217923 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7924 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7925 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7926 session_deps.socket_factory.AddSSLSocketDataProvider(
7927 &ssl_socket_data_provider1);
7928 session_deps.socket_factory.AddSSLSocketDataProvider(
7929 &ssl_socket_data_provider2);
7930
[email protected]e60e47a2010-07-14 03:37:187931 // Work around http://crbug.com/37454
7932 StaticSocketDataProvider bug37454_connection;
[email protected]d973e99a2012-02-17 21:02:367933 bug37454_connection.set_connect_data(MockConnect(ASYNC, ERR_UNEXPECTED));
[email protected]e60e47a2010-07-14 03:37:187934 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7935
[email protected]aeaca1f2010-04-20 22:05:217936 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7937 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417938 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:217939
[email protected]49639fa2011-12-20 23:22:417940 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217941 EXPECT_EQ(ERR_IO_PENDING, rv);
7942 EXPECT_EQ(OK, callback.WaitForResult());
7943
7944 const HttpResponseInfo* response = trans->GetResponseInfo();
7945 ASSERT_TRUE(response != NULL);
7946 ASSERT_TRUE(response->headers != NULL);
7947 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7948
7949 std::string response_data;
7950 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7951 EXPECT_EQ("ok.", response_data);
7952}
7953
7954// Test that we restart a connection if we get a decompression failure from the
7955// peer while reading the first bytes from the connection. This occurs when the
7956// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7957// in the handshake.
7958TEST_F(HttpNetworkTransactionTest,
7959 RestartAfterTLSDecompressionFailureWithFalseStart) {
7960 HttpRequestInfo request;
7961 request.method = "GET";
7962 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7963 request.load_flags = 0;
7964
7965 SessionDependencies session_deps;
7966 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7967 true /* fail all reads */);
7968 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7969 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7970 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7971 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7972 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7973 session_deps.socket_factory.AddSSLSocketDataProvider(
7974 &ssl_socket_data_provider1);
7975 session_deps.socket_factory.AddSSLSocketDataProvider(
7976 &ssl_socket_data_provider2);
7977
7978 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7979 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417980 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:217981
[email protected]49639fa2011-12-20 23:22:417982 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217983 EXPECT_EQ(ERR_IO_PENDING, rv);
7984 EXPECT_EQ(OK, callback.WaitForResult());
7985
7986 const HttpResponseInfo* response = trans->GetResponseInfo();
7987 ASSERT_TRUE(response != NULL);
7988 ASSERT_TRUE(response->headers != NULL);
7989 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7990
7991 std::string response_data;
7992 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7993 EXPECT_EQ("ok.", response_data);
7994}
7995
[email protected]65041fa2010-05-21 06:56:537996// This tests the case that a request is issued via http instead of spdy after
7997// npn is negotiated.
7998TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387999 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348000 HttpStreamFactory::set_next_protos(
8001 MakeNextProtos("http/1.1", "http1.1", NULL));
[email protected]65041fa2010-05-21 06:56:538002 SessionDependencies session_deps;
8003 HttpRequestInfo request;
8004 request.method = "GET";
8005 request.url = GURL("https://www.google.com/");
8006 request.load_flags = 0;
8007
8008 MockWrite data_writes[] = {
8009 MockWrite("GET / HTTP/1.1\r\n"
8010 "Host: www.google.com\r\n"
8011 "Connection: keep-alive\r\n\r\n"),
8012 };
8013
8014 MockRead data_reads[] = {
8015 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:358016 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:538017 MockRead("hello world"),
8018 MockRead(false, OK),
8019 };
8020
8021 SSLSocketDataProvider ssl(true, OK);
8022 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8023 ssl.next_proto = "http/1.1";
[email protected]c30bcce2011-12-20 17:50:518024 ssl.protocol_negotiated = SSLClientSocket::kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:538025
8026 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8027
8028 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8029 data_writes, arraysize(data_writes));
8030 session_deps.socket_factory.AddSocketDataProvider(&data);
8031
[email protected]49639fa2011-12-20 23:22:418032 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:538033
8034 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8035 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8036
[email protected]49639fa2011-12-20 23:22:418037 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:538038
8039 EXPECT_EQ(ERR_IO_PENDING, rv);
8040 EXPECT_EQ(OK, callback.WaitForResult());
8041
8042 const HttpResponseInfo* response = trans->GetResponseInfo();
8043 ASSERT_TRUE(response != NULL);
8044 ASSERT_TRUE(response->headers != NULL);
8045 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8046
8047 std::string response_data;
8048 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8049 EXPECT_EQ("hello world", response_data);
8050
8051 EXPECT_FALSE(response->was_fetched_via_spdy);
8052 EXPECT_TRUE(response->was_npn_negotiated);
8053
[email protected]5285d972011-10-18 18:56:348054 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388055 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:538056}
[email protected]26ef6582010-06-24 02:30:478057
8058TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8059 // Simulate the SSL handshake completing with an NPN negotiation
8060 // followed by an immediate server closing of the socket.
8061 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:388062 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348063 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]26ef6582010-06-24 02:30:478064 SessionDependencies session_deps;
8065
8066 HttpRequestInfo request;
8067 request.method = "GET";
8068 request.url = GURL("https://www.google.com/");
8069 request.load_flags = 0;
8070
8071 SSLSocketDataProvider ssl(true, OK);
[email protected]e58c1b82012-02-22 23:07:518072 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]26ef6582010-06-24 02:30:478073 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8074
[email protected]2bd93022010-07-17 00:58:448075 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:138076 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:478077
8078 MockRead spdy_reads[] = {
8079 MockRead(false, 0, 0) // Not async - return 0 immediately.
8080 };
8081
[email protected]a1595312012-01-22 03:25:048082 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]26ef6582010-06-24 02:30:478083 new DelayedSocketData(
8084 0, // don't wait in this case, immediate hangup.
8085 spdy_reads, arraysize(spdy_reads),
8086 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048087 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]26ef6582010-06-24 02:30:478088
[email protected]49639fa2011-12-20 23:22:418089 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:478090
8091 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8092 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8093
[email protected]49639fa2011-12-20 23:22:418094 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:478095 EXPECT_EQ(ERR_IO_PENDING, rv);
8096 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8097
[email protected]5285d972011-10-18 18:56:348098 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388099 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:478100}
[email protected]65d34382010-07-01 18:12:268101
[email protected]f45c1ee2010-08-03 00:54:308102TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8103 // This test ensures that the URL passed into the proxy is upgraded
8104 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:388105 HttpStreamFactory::set_use_alternate_protocols(true);
8106 HttpStreamFactory::set_next_protos(
[email protected]42baef7a2011-12-10 04:52:108107 MakeNextProtos(
8108 "http/1.1", "http1.1", "spdy/2.1", "spdy/2", "spdy", NULL));
[email protected]f45c1ee2010-08-03 00:54:308109
[email protected]81cdfcd2010-10-16 00:49:008110 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:308111 HttpAuthHandlerMock::Factory* auth_factory =
8112 new HttpAuthHandlerMock::Factory();
[email protected]767257802011-12-14 17:33:188113 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
8114 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:308115 auth_factory->set_do_init_from_challenge(true);
8116 session_deps.http_auth_handler_factory.reset(auth_factory);
8117
8118 HttpRequestInfo request;
8119 request.method = "GET";
8120 request.url = GURL("http://www.google.com");
8121 request.load_flags = 0;
8122
8123 // First round goes unauthenticated through the proxy.
8124 MockWrite data_writes_1[] = {
8125 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8126 "Host: www.google.com\r\n"
8127 "Proxy-Connection: keep-alive\r\n"
8128 "\r\n"),
8129 };
8130 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:598131 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:308132 MockRead("HTTP/1.1 200 OK\r\n"
[email protected]8d2f7012012-02-16 00:08:048133 "Alternate-Protocol: 443:npn-spdy/2.1\r\n"
[email protected]f45c1ee2010-08-03 00:54:308134 "Proxy-Connection: close\r\n"
8135 "\r\n"),
8136 };
8137 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8138 data_writes_1, arraysize(data_writes_1));
8139
8140 // Second round tries to tunnel to www.google.com due to the
8141 // Alternate-Protocol announcement in the first round. It fails due
8142 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:598143 // After the failure, a tunnel is established to www.google.com using
8144 // Proxy-Authorization headers. There is then a SPDY request round.
8145 //
[email protected]fe3b7dc2012-02-03 19:52:098146 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8147 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8148 // does a Disconnect and Connect on the same socket, rather than trying
8149 // to obtain a new one.
8150 //
[email protected]394816e92010-08-03 07:38:598151 // NOTE: Originally, the proxy response to the second CONNECT request
8152 // simply returned another 407 so the unit test could skip the SSL connection
8153 // establishment and SPDY framing issues. Alas, the
8154 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308155 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598156
[email protected]f45c1ee2010-08-03 00:54:308157 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8158 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8159 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8160
[email protected]394816e92010-08-03 07:38:598161 MockWrite data_writes_2[] = {
8162 // First connection attempt without Proxy-Authorization.
8163 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8164 "Host: www.google.com\r\n"
8165 "Proxy-Connection: keep-alive\r\n"
8166 "\r\n"),
8167
8168 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308169 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8170 "Host: www.google.com\r\n"
8171 "Proxy-Connection: keep-alive\r\n"
8172 "Proxy-Authorization: auth_token\r\n"
8173 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308174
[email protected]394816e92010-08-03 07:38:598175 // SPDY request
8176 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308177 };
[email protected]394816e92010-08-03 07:38:598178 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8179 "Proxy-Authenticate: Mock\r\n"
8180 "Proxy-Connection: close\r\n"
8181 "\r\n");
8182 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8183 MockRead data_reads_2[] = {
8184 // First connection attempt fails
8185 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8186 MockRead(true, kRejectConnectResponse,
8187 arraysize(kRejectConnectResponse) - 1, 1),
8188
8189 // Second connection attempt passes
8190 MockRead(true, kAcceptConnectResponse,
[email protected]fe3b7dc2012-02-03 19:52:098191 arraysize(kAcceptConnectResponse) -1, 4),
[email protected]394816e92010-08-03 07:38:598192
8193 // SPDY response
[email protected]fe3b7dc2012-02-03 19:52:098194 CreateMockRead(*resp.get(), 6),
8195 CreateMockRead(*data.get(), 6),
8196 MockRead(true, 0, 0, 6),
[email protected]394816e92010-08-03 07:38:598197 };
[email protected]a1595312012-01-22 03:25:048198 scoped_ptr<OrderedSocketData> data_2(
[email protected]394816e92010-08-03 07:38:598199 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8200 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308201
8202 SSLSocketDataProvider ssl(true, OK);
8203 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208204 ssl.next_proto = "spdy/2.1";
[email protected]f45c1ee2010-08-03 00:54:308205 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208206 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]f45c1ee2010-08-03 00:54:308207
[email protected]d973e99a2012-02-17 21:02:368208 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:558209 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8210 NULL, 0, NULL, 0);
8211 hanging_non_alternate_protocol_socket.set_connect_data(
8212 never_finishing_connect);
8213
[email protected]f45c1ee2010-08-03 00:54:308214 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598215 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308216 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558217 session_deps.socket_factory.AddSocketDataProvider(
8218 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308219 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8220
8221 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:418222 TestCompletionCallback callback_1;
[email protected]f45c1ee2010-08-03 00:54:308223 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418224 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308225 EXPECT_EQ(ERR_IO_PENDING, rv);
8226 EXPECT_EQ(OK, callback_1.WaitForResult());
8227
8228 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:418229 TestCompletionCallback callback_2;
[email protected]f45c1ee2010-08-03 00:54:308230 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418231 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308232 EXPECT_EQ(ERR_IO_PENDING, rv);
8233 EXPECT_EQ(OK, callback_2.WaitForResult());
8234 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508235 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:308236 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8237
8238 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:418239 TestCompletionCallback callback_3;
8240 rv = trans_2->RestartWithAuth(
8241 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:308242 EXPECT_EQ(ERR_IO_PENDING, rv);
8243 EXPECT_EQ(OK, callback_3.WaitForResult());
8244
8245 // After all that work, these two lines (or actually, just the scheme) are
8246 // what this test is all about. Make sure it happens correctly.
[email protected]767257802011-12-14 17:33:188247 const GURL& request_url = auth_handler->request_url();
[email protected]f45c1ee2010-08-03 00:54:308248 EXPECT_EQ("https", request_url.scheme());
8249 EXPECT_EQ("www.google.com", request_url.host());
8250
[email protected]5285d972011-10-18 18:56:348251 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388252 HttpStreamFactory::set_use_alternate_protocols(false);
8253}
8254
8255// Test that if we cancel the transaction as the connection is completing, that
8256// everything tears down correctly.
8257TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8258 // Setup everything about the connection to complete synchronously, so that
8259 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8260 // for is the callback from the HttpStreamRequest.
8261 // Then cancel the transaction.
8262 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:368263 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:388264 MockRead data_reads[] = {
8265 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8266 MockRead(false, "hello world"),
8267 MockRead(false, OK),
8268 };
8269
[email protected]8e6441ca2010-08-19 05:56:388270 HttpRequestInfo request;
8271 request.method = "GET";
8272 request.url = GURL("http://www.google.com/");
8273 request.load_flags = 0;
8274
[email protected]cb9bf6ca2011-01-28 13:15:278275 SessionDependencies session_deps;
8276 session_deps.host_resolver->set_synchronous_mode(true);
8277 scoped_ptr<HttpTransaction> trans(
8278 new HttpNetworkTransaction(CreateSession(&session_deps)));
8279
[email protected]8e6441ca2010-08-19 05:56:388280 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8281 data.set_connect_data(mock_connect);
8282 session_deps.socket_factory.AddSocketDataProvider(&data);
8283
[email protected]49639fa2011-12-20 23:22:418284 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:388285
8286 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]49639fa2011-12-20 23:22:418287 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:388288 EXPECT_EQ(ERR_IO_PENDING, rv);
8289 trans.reset(); // Cancel the transaction here.
8290
8291 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308292}
8293
[email protected]76a505b2010-08-25 06:23:008294// Test a basic GET request through a proxy.
8295TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008296 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008297 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8298 session_deps.net_log = log.bound().net_log();
8299 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8300
[email protected]76a505b2010-08-25 06:23:008301 HttpRequestInfo request;
8302 request.method = "GET";
8303 request.url = GURL("http://www.google.com/");
8304
8305 MockWrite data_writes1[] = {
8306 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8307 "Host: www.google.com\r\n"
8308 "Proxy-Connection: keep-alive\r\n\r\n"),
8309 };
8310
8311 MockRead data_reads1[] = {
8312 MockRead("HTTP/1.1 200 OK\r\n"),
8313 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8314 MockRead("Content-Length: 100\r\n\r\n"),
8315 MockRead(false, OK),
8316 };
8317
8318 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8319 data_writes1, arraysize(data_writes1));
8320 session_deps.socket_factory.AddSocketDataProvider(&data1);
8321
[email protected]49639fa2011-12-20 23:22:418322 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008323
[email protected]0b0bf032010-09-21 18:08:508324 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8325
[email protected]49639fa2011-12-20 23:22:418326 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008327 EXPECT_EQ(ERR_IO_PENDING, rv);
8328
8329 rv = callback1.WaitForResult();
8330 EXPECT_EQ(OK, rv);
8331
8332 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508333 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008334
8335 EXPECT_TRUE(response->headers->IsKeepAlive());
8336 EXPECT_EQ(200, response->headers->response_code());
8337 EXPECT_EQ(100, response->headers->GetContentLength());
8338 EXPECT_TRUE(response->was_fetched_via_proxy);
8339 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8340}
8341
8342// Test a basic HTTPS GET request through a proxy.
8343TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008344 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008345 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8346 session_deps.net_log = log.bound().net_log();
8347 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8348
[email protected]76a505b2010-08-25 06:23:008349 HttpRequestInfo request;
8350 request.method = "GET";
8351 request.url = GURL("https://www.google.com/");
8352
8353 // Since we have proxy, should try to establish tunnel.
8354 MockWrite data_writes1[] = {
8355 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8356 "Host: www.google.com\r\n"
8357 "Proxy-Connection: keep-alive\r\n\r\n"),
8358
8359 MockWrite("GET / HTTP/1.1\r\n"
8360 "Host: www.google.com\r\n"
8361 "Connection: keep-alive\r\n\r\n"),
8362 };
8363
8364 MockRead data_reads1[] = {
8365 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8366
8367 MockRead("HTTP/1.1 200 OK\r\n"),
8368 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8369 MockRead("Content-Length: 100\r\n\r\n"),
8370 MockRead(false, OK),
8371 };
8372
8373 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8374 data_writes1, arraysize(data_writes1));
8375 session_deps.socket_factory.AddSocketDataProvider(&data1);
8376 SSLSocketDataProvider ssl(true, OK);
8377 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8378
[email protected]49639fa2011-12-20 23:22:418379 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008380
[email protected]0b0bf032010-09-21 18:08:508381 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8382
[email protected]49639fa2011-12-20 23:22:418383 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008384 EXPECT_EQ(ERR_IO_PENDING, rv);
8385
8386 rv = callback1.WaitForResult();
8387 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408388 net::CapturingNetLog::EntryList entries;
8389 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008390 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408391 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008392 NetLog::PHASE_NONE);
8393 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408394 entries, pos,
[email protected]76a505b2010-08-25 06:23:008395 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8396 NetLog::PHASE_NONE);
8397
8398 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508399 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008400
8401 EXPECT_TRUE(response->headers->IsKeepAlive());
8402 EXPECT_EQ(200, response->headers->response_code());
8403 EXPECT_EQ(100, response->headers->GetContentLength());
8404 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8405 EXPECT_TRUE(response->was_fetched_via_proxy);
8406}
8407
8408// Test a basic HTTPS GET request through a proxy, but the server hangs up
8409// while establishing the tunnel.
8410TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008411 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008412 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8413 session_deps.net_log = log.bound().net_log();
8414 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8415
[email protected]76a505b2010-08-25 06:23:008416 HttpRequestInfo request;
8417 request.method = "GET";
8418 request.url = GURL("https://www.google.com/");
8419
8420 // Since we have proxy, should try to establish tunnel.
8421 MockWrite data_writes1[] = {
8422 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8423 "Host: www.google.com\r\n"
8424 "Proxy-Connection: keep-alive\r\n\r\n"),
8425
8426 MockWrite("GET / HTTP/1.1\r\n"
8427 "Host: www.google.com\r\n"
8428 "Connection: keep-alive\r\n\r\n"),
8429 };
8430
8431 MockRead data_reads1[] = {
8432 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8433 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8434 MockRead(true, 0, 0), // EOF
8435 };
8436
8437 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8438 data_writes1, arraysize(data_writes1));
8439 session_deps.socket_factory.AddSocketDataProvider(&data1);
8440 SSLSocketDataProvider ssl(true, OK);
8441 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8442
[email protected]49639fa2011-12-20 23:22:418443 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008444
[email protected]0b0bf032010-09-21 18:08:508445 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8446
[email protected]49639fa2011-12-20 23:22:418447 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008448 EXPECT_EQ(ERR_IO_PENDING, rv);
8449
8450 rv = callback1.WaitForResult();
8451 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408452 net::CapturingNetLog::EntryList entries;
8453 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008454 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408455 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008456 NetLog::PHASE_NONE);
8457 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408458 entries, pos,
[email protected]76a505b2010-08-25 06:23:008459 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8460 NetLog::PHASE_NONE);
8461}
8462
[email protected]749eefa82010-09-13 22:14:038463// Test for crbug.com/55424.
8464TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8465 SessionDependencies session_deps;
8466
8467 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8468 "https://www.google.com", false, 1, LOWEST));
8469 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8470
8471 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8472 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8473 MockRead spdy_reads[] = {
8474 CreateMockRead(*resp),
8475 CreateMockRead(*data),
8476 MockRead(true, 0, 0),
8477 };
8478
[email protected]a1595312012-01-22 03:25:048479 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]749eefa82010-09-13 22:14:038480 new DelayedSocketData(
8481 1, // wait for one write to finish before reading.
8482 spdy_reads, arraysize(spdy_reads),
8483 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048484 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]749eefa82010-09-13 22:14:038485
8486 SSLSocketDataProvider ssl(true, OK);
8487 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208488 ssl.next_proto = "spdy/2.1";
[email protected]749eefa82010-09-13 22:14:038489 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208490 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]749eefa82010-09-13 22:14:038491 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8492
8493 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8494
8495 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388496 HostPortPair host_port_pair("www.google.com", 443);
8497 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038498 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318499 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288500 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:298501 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]6ecf2b92011-12-15 01:14:528502 TestCompletionCallback callback;
[email protected]02b0c342010-09-25 21:09:388503
8504 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8505 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288506 connection->Init(host_port_pair.ToString(), transport_params,
[email protected]6ecf2b92011-12-15 01:14:528507 LOWEST, callback.callback(),
[email protected]a42dbd142011-11-17 16:42:028508 session->GetTransportSocketPool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388509 EXPECT_EQ(OK, callback.WaitForResult());
8510 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038511
8512 HttpRequestInfo request;
8513 request.method = "GET";
8514 request.url = GURL("https://www.google.com/");
8515 request.load_flags = 0;
8516
8517 // This is the important line that marks this as a preconnect.
8518 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8519
8520 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8521
[email protected]49639fa2011-12-20 23:22:418522 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:038523 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:418524 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:038525}
8526
[email protected]73b8dd222010-11-11 19:55:248527// Given a net error, cause that error to be returned from the first Write()
8528// call and verify that the HttpTransaction fails with that error.
8529static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278530 net::HttpRequestInfo request_info;
8531 request_info.url = GURL("https://www.example.com/");
8532 request_info.method = "GET";
8533 request_info.load_flags = net::LOAD_NORMAL;
8534
[email protected]73b8dd222010-11-11 19:55:248535 SessionDependencies session_deps;
8536
8537 SSLSocketDataProvider ssl_data(async, OK);
8538 net::MockWrite data_writes[] = {
8539 net::MockWrite(async, error),
8540 };
8541 net::StaticSocketDataProvider data(NULL, 0,
8542 data_writes, arraysize(data_writes));
8543 session_deps.socket_factory.AddSocketDataProvider(&data);
8544 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8545
8546 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8547 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8548
[email protected]49639fa2011-12-20 23:22:418549 TestCompletionCallback callback;
8550 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]73b8dd222010-11-11 19:55:248551 if (rv == net::ERR_IO_PENDING)
8552 rv = callback.WaitForResult();
8553 ASSERT_EQ(error, rv);
8554}
8555
8556TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8557 // Just check a grab bag of cert errors.
8558 static const int kErrors[] = {
8559 ERR_CERT_COMMON_NAME_INVALID,
8560 ERR_CERT_AUTHORITY_INVALID,
8561 ERR_CERT_DATE_INVALID,
8562 };
8563 for (size_t i = 0; i < arraysize(kErrors); i++) {
8564 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8565 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8566 }
8567}
8568
[email protected]bd0b6772011-01-11 19:59:308569// Ensure that a client certificate is removed from the SSL client auth
8570// cache when:
8571// 1) No proxy is involved.
8572// 2) TLS False Start is disabled.
8573// 3) The initial TLS handshake requests a client certificate.
8574// 4) The client supplies an invalid/unacceptable certificate.
8575TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278576 net::HttpRequestInfo request_info;
8577 request_info.url = GURL("https://www.example.com/");
8578 request_info.method = "GET";
8579 request_info.load_flags = net::LOAD_NORMAL;
8580
[email protected]bd0b6772011-01-11 19:59:308581 SessionDependencies session_deps;
8582
8583 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8584 cert_request->host_and_port = "www.example.com:443";
8585
8586 // [ssl_]data1 contains the data for the first SSL handshake. When a
8587 // CertificateRequest is received for the first time, the handshake will
8588 // be aborted to allow the caller to provide a certificate.
8589 SSLSocketDataProvider ssl_data1(true /* async */,
8590 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8591 ssl_data1.cert_request_info = cert_request.get();
8592 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8593 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8594 session_deps.socket_factory.AddSocketDataProvider(&data1);
8595
8596 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8597 // False Start is not being used, the result of the SSL handshake will be
8598 // returned as part of the SSLClientSocket::Connect() call. This test
8599 // matches the result of a server sending a handshake_failure alert,
8600 // rather than a Finished message, because it requires a client
8601 // certificate and none was supplied.
8602 SSLSocketDataProvider ssl_data2(true /* async */,
8603 net::ERR_SSL_PROTOCOL_ERROR);
8604 ssl_data2.cert_request_info = cert_request.get();
8605 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8606 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8607 session_deps.socket_factory.AddSocketDataProvider(&data2);
8608
8609 // [ssl_]data3 contains the data for the third SSL handshake. When a
8610 // connection to a server fails during an SSL handshake,
8611 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8612 // connection was attempted with TLSv1. This is transparent to the caller
8613 // of the HttpNetworkTransaction. Because this test failure is due to
8614 // requiring a client certificate, this fallback handshake should also
8615 // fail.
8616 SSLSocketDataProvider ssl_data3(true /* async */,
8617 net::ERR_SSL_PROTOCOL_ERROR);
8618 ssl_data3.cert_request_info = cert_request.get();
8619 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8620 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8621 session_deps.socket_factory.AddSocketDataProvider(&data3);
8622
8623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8624 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8625
[email protected]bd0b6772011-01-11 19:59:308626 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:418627 TestCompletionCallback callback;
8628 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308629 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8630
8631 // Complete the SSL handshake, which should abort due to requiring a
8632 // client certificate.
8633 rv = callback.WaitForResult();
8634 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8635
8636 // Indicate that no certificate should be supplied. From the perspective
8637 // of SSLClientCertCache, NULL is just as meaningful as a real
8638 // certificate, so this is the same as supply a
8639 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418640 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308641 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8642
8643 // Ensure the certificate was added to the client auth cache before
8644 // allowing the connection to continue restarting.
8645 scoped_refptr<X509Certificate> client_cert;
8646 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8647 &client_cert));
8648 ASSERT_EQ(NULL, client_cert.get());
8649
8650 // Restart the handshake. This will consume ssl_data2, which fails, and
8651 // then consume ssl_data3, which should also fail. The result code is
8652 // checked against what ssl_data3 should return.
8653 rv = callback.WaitForResult();
8654 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8655
8656 // Ensure that the client certificate is removed from the cache on a
8657 // handshake failure.
8658 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8659 &client_cert));
8660}
8661
8662// Ensure that a client certificate is removed from the SSL client auth
8663// cache when:
8664// 1) No proxy is involved.
8665// 2) TLS False Start is enabled.
8666// 3) The initial TLS handshake requests a client certificate.
8667// 4) The client supplies an invalid/unacceptable certificate.
8668TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278669 net::HttpRequestInfo request_info;
8670 request_info.url = GURL("https://www.example.com/");
8671 request_info.method = "GET";
8672 request_info.load_flags = net::LOAD_NORMAL;
8673
[email protected]bd0b6772011-01-11 19:59:308674 SessionDependencies session_deps;
8675
8676 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8677 cert_request->host_and_port = "www.example.com:443";
8678
8679 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8680 // return successfully after reading up to the peer's Certificate message.
8681 // This is to allow the caller to call SSLClientSocket::Write(), which can
8682 // enqueue application data to be sent in the same packet as the
8683 // ChangeCipherSpec and Finished messages.
8684 // The actual handshake will be finished when SSLClientSocket::Read() is
8685 // called, which expects to process the peer's ChangeCipherSpec and
8686 // Finished messages. If there was an error negotiating with the peer,
8687 // such as due to the peer requiring a client certificate when none was
8688 // supplied, the alert sent by the peer won't be processed until Read() is
8689 // called.
8690
8691 // Like the non-False Start case, when a client certificate is requested by
8692 // the peer, the handshake is aborted during the Connect() call.
8693 // [ssl_]data1 represents the initial SSL handshake with the peer.
8694 SSLSocketDataProvider ssl_data1(true /* async */,
8695 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8696 ssl_data1.cert_request_info = cert_request.get();
8697 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8698 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8699 session_deps.socket_factory.AddSocketDataProvider(&data1);
8700
8701 // When a client certificate is supplied, Connect() will not be aborted
8702 // when the peer requests the certificate. Instead, the handshake will
8703 // artificially succeed, allowing the caller to write the HTTP request to
8704 // the socket. The handshake messages are not processed until Read() is
8705 // called, which then detects that the handshake was aborted, due to the
8706 // peer sending a handshake_failure because it requires a client
8707 // certificate.
8708 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8709 ssl_data2.cert_request_info = cert_request.get();
8710 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8711 net::MockRead data2_reads[] = {
8712 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8713 };
8714 net::StaticSocketDataProvider data2(
8715 data2_reads, arraysize(data2_reads), NULL, 0);
8716 session_deps.socket_factory.AddSocketDataProvider(&data2);
8717
8718 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8719 // the data for the SSL handshake once the TLSv1 connection falls back to
8720 // SSLv3. It has the same behaviour as [ssl_]data2.
8721 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8722 ssl_data3.cert_request_info = cert_request.get();
8723 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8724 net::StaticSocketDataProvider data3(
8725 data2_reads, arraysize(data2_reads), NULL, 0);
8726 session_deps.socket_factory.AddSocketDataProvider(&data3);
8727
8728 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8729 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8730
[email protected]bd0b6772011-01-11 19:59:308731 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:418732 TestCompletionCallback callback;
8733 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308734 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8735
8736 // Complete the SSL handshake, which should abort due to requiring a
8737 // client certificate.
8738 rv = callback.WaitForResult();
8739 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8740
8741 // Indicate that no certificate should be supplied. From the perspective
8742 // of SSLClientCertCache, NULL is just as meaningful as a real
8743 // certificate, so this is the same as supply a
8744 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418745 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308746 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8747
8748 // Ensure the certificate was added to the client auth cache before
8749 // allowing the connection to continue restarting.
8750 scoped_refptr<X509Certificate> client_cert;
8751 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8752 &client_cert));
8753 ASSERT_EQ(NULL, client_cert.get());
8754
8755
8756 // Restart the handshake. This will consume ssl_data2, which fails, and
8757 // then consume ssl_data3, which should also fail. The result code is
8758 // checked against what ssl_data3 should return.
8759 rv = callback.WaitForResult();
8760 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8761
8762 // Ensure that the client certificate is removed from the cache on a
8763 // handshake failure.
8764 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8765 &client_cert));
8766}
8767
[email protected]8c405132011-01-11 22:03:188768// Ensure that a client certificate is removed from the SSL client auth
8769// cache when:
8770// 1) An HTTPS proxy is involved.
8771// 3) The HTTPS proxy requests a client certificate.
8772// 4) The client supplies an invalid/unacceptable certificate for the
8773// proxy.
8774// The test is repeated twice, first for connecting to an HTTPS endpoint,
8775// then for connecting to an HTTP endpoint.
8776TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8777 SessionDependencies session_deps(
8778 ProxyService::CreateFixed("https://proxy:70"));
8779 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8780 session_deps.net_log = log.bound().net_log();
8781
8782 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8783 cert_request->host_and_port = "proxy:70";
8784
8785 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8786 // [ssl_]data[1-3]. Rather than represending the endpoint
8787 // (www.example.com:443), they represent failures with the HTTPS proxy
8788 // (proxy:70).
8789 SSLSocketDataProvider ssl_data1(true /* async */,
8790 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8791 ssl_data1.cert_request_info = cert_request.get();
8792 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8793 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8794 session_deps.socket_factory.AddSocketDataProvider(&data1);
8795
8796 SSLSocketDataProvider ssl_data2(true /* async */,
8797 net::ERR_SSL_PROTOCOL_ERROR);
8798 ssl_data2.cert_request_info = cert_request.get();
8799 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8800 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8801 session_deps.socket_factory.AddSocketDataProvider(&data2);
8802
8803 SSLSocketDataProvider ssl_data3(true /* async */,
8804 net::ERR_SSL_PROTOCOL_ERROR);
8805 ssl_data3.cert_request_info = cert_request.get();
8806 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8807 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8808 session_deps.socket_factory.AddSocketDataProvider(&data3);
8809
8810 net::HttpRequestInfo requests[2];
8811 requests[0].url = GURL("https://www.example.com/");
8812 requests[0].method = "GET";
8813 requests[0].load_flags = net::LOAD_NORMAL;
8814
8815 requests[1].url = GURL("http://www.example.com/");
8816 requests[1].method = "GET";
8817 requests[1].load_flags = net::LOAD_NORMAL;
8818
8819 for (size_t i = 0; i < arraysize(requests); ++i) {
8820 session_deps.socket_factory.ResetNextMockIndexes();
8821 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8822 scoped_ptr<HttpNetworkTransaction> trans(
8823 new HttpNetworkTransaction(session));
8824
8825 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:418826 TestCompletionCallback callback;
8827 int rv = trans->Start(
8828 &requests[i], callback.callback(), net::BoundNetLog());
[email protected]8c405132011-01-11 22:03:188829 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8830
8831 // Complete the SSL handshake, which should abort due to requiring a
8832 // client certificate.
8833 rv = callback.WaitForResult();
8834 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8835
8836 // Indicate that no certificate should be supplied. From the perspective
8837 // of SSLClientCertCache, NULL is just as meaningful as a real
8838 // certificate, so this is the same as supply a
8839 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418840 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]8c405132011-01-11 22:03:188841 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8842
8843 // Ensure the certificate was added to the client auth cache before
8844 // allowing the connection to continue restarting.
8845 scoped_refptr<X509Certificate> client_cert;
8846 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8847 &client_cert));
8848 ASSERT_EQ(NULL, client_cert.get());
8849 // Ensure the certificate was NOT cached for the endpoint. This only
8850 // applies to HTTPS requests, but is fine to check for HTTP requests.
8851 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8852 &client_cert));
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_PROXY_CONNECTION_FAILED, rv);
8859
8860 // Now that the new handshake has failed, ensure that the client
8861 // certificate was removed from the client auth cache.
8862 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8863 &client_cert));
8864 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8865 &client_cert));
8866 }
8867}
8868
[email protected]5c288bc2011-07-26 15:12:058869void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8870 SpdySessionPoolPeer* pool_peer,
8871 std::string host,
8872 int port,
8873 std::string iplist) {
8874 // Create a host resolver dependency that returns address |iplist| for
8875 // resolutions of |host|.
8876 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:048877
[email protected]5c288bc2011-07-26 15:12:058878 // Setup a HostPortProxyPair.
8879 HostPortPair host_port_pair(host, port);
8880 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
8881 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:048882
[email protected]5c288bc2011-07-26 15:12:058883 // Resolve the host and port.
8884 AddressList addresses;
8885 HostResolver::RequestInfo info(host_port_pair);
[email protected]aa22b242011-11-16 18:58:298886 TestCompletionCallback callback;
8887 int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:478888 BoundNetLog());
8889 if (rv == ERR_IO_PENDING)
8890 rv = callback.WaitForResult();
8891 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:048892
[email protected]5c288bc2011-07-26 15:12:058893 // Add the first address as an alias. It would have been better to call
8894 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
8895 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
8896 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
8897 // the |pair|.
8898 const addrinfo* address = addresses.head();
8899 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:048900}
8901
[email protected]e3ceb682011-06-28 23:55:468902TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
8903 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348904 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:468905
8906 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
8907 SessionDependencies session_deps;
8908 MockCachingHostResolver host_resolver;
8909 net::HttpNetworkSession::Params params;
8910 params.client_socket_factory = &session_deps.socket_factory;
8911 params.host_resolver = &host_resolver;
8912 params.cert_verifier = session_deps.cert_verifier.get();
8913 params.proxy_service = session_deps.proxy_service.get();
8914 params.ssl_config_service = session_deps.ssl_config_service;
8915 params.http_auth_handler_factory =
8916 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:538917 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:468918 params.net_log = session_deps.net_log;
8919 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268920 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8921 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468922
8923 SSLSocketDataProvider ssl(true, OK);
8924 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208925 ssl.next_proto = "spdy/2.1";
[email protected]e3ceb682011-06-28 23:55:468926 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208927 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]e3ceb682011-06-28 23:55:468928 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8929
8930 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8931 "https://www.google.com", false, 1, LOWEST));
8932 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8933 "https://www.gmail.com", false, 3, LOWEST));
8934 MockWrite spdy_writes[] = {
8935 CreateMockWrite(*host1_req, 1),
8936 CreateMockWrite(*host2_req, 4),
8937 };
8938 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8939 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8940 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8941 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8942 MockRead spdy_reads[] = {
8943 CreateMockRead(*host1_resp, 2),
8944 CreateMockRead(*host1_resp_body, 3),
8945 CreateMockRead(*host2_resp, 5),
8946 CreateMockRead(*host2_resp_body, 6),
8947 MockRead(true, 0, 7),
8948 };
8949
[email protected]a1595312012-01-22 03:25:048950 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:468951 new OrderedSocketData(
8952 spdy_reads, arraysize(spdy_reads),
8953 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048954 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:468955
[email protected]aa22b242011-11-16 18:58:298956 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:468957 HttpRequestInfo request1;
8958 request1.method = "GET";
8959 request1.url = GURL("https://www.google.com/");
8960 request1.load_flags = 0;
8961 HttpNetworkTransaction trans1(session);
8962
[email protected]49639fa2011-12-20 23:22:418963 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:468964 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:418965 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:468966
8967 const HttpResponseInfo* response = trans1.GetResponseInfo();
8968 ASSERT_TRUE(response != NULL);
8969 ASSERT_TRUE(response->headers != NULL);
8970 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8971
8972 std::string response_data;
8973 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
8974 EXPECT_EQ("hello!", response_data);
8975
8976 // Preload www.gmail.com into HostCache.
8977 HostPortPair host_port("www.gmail.com", 443);
8978 HostResolver::RequestInfo resolve_info(host_port);
8979 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:298980 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:478981 BoundNetLog());
8982 EXPECT_EQ(ERR_IO_PENDING, rv);
8983 rv = callback.WaitForResult();
8984 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:468985
[email protected]5c288bc2011-07-26 15:12:058986 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
8987 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
8988 // (www.google.com, 443).
8989 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
8990 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:048991
[email protected]e3ceb682011-06-28 23:55:468992 HttpRequestInfo request2;
8993 request2.method = "GET";
8994 request2.url = GURL("https://www.gmail.com/");
8995 request2.load_flags = 0;
8996 HttpNetworkTransaction trans2(session);
8997
[email protected]49639fa2011-12-20 23:22:418998 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:468999 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419000 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469001
9002 response = trans2.GetResponseInfo();
9003 ASSERT_TRUE(response != NULL);
9004 ASSERT_TRUE(response->headers != NULL);
9005 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9006 EXPECT_TRUE(response->was_fetched_via_spdy);
9007 EXPECT_TRUE(response->was_npn_negotiated);
9008 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9009 EXPECT_EQ("hello!", response_data);
9010
[email protected]5285d972011-10-18 18:56:349011 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469012 HttpStreamFactory::set_use_alternate_protocols(false);
9013}
9014
9015class OneTimeCachingHostResolver : public net::HostResolver {
9016 public:
9017 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9018 : host_port_(host_port) {}
9019 virtual ~OneTimeCachingHostResolver() {}
9020
9021 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9022
9023 // HostResolver methods:
9024 virtual int Resolve(const RequestInfo& info,
9025 AddressList* addresses,
[email protected]aa22b242011-11-16 18:58:299026 const CompletionCallback& callback,
[email protected]e3ceb682011-06-28 23:55:469027 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:409028 const BoundNetLog& net_log) OVERRIDE {
9029 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:469030 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:409031 }
9032
9033 virtual int ResolveFromCache(const RequestInfo& info,
9034 AddressList* addresses,
9035 const BoundNetLog& net_log) OVERRIDE {
9036 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9037 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:099038 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:469039 return rv;
9040 }
9041
[email protected]95a214c2011-08-04 21:50:409042 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469043 host_resolver_.CancelRequest(req);
9044 }
9045
[email protected]46da33be2011-07-19 21:58:049046 MockCachingHostResolver* GetMockHostResolver() {
9047 return &host_resolver_;
9048 }
9049
[email protected]e3ceb682011-06-28 23:55:469050 private:
9051 MockCachingHostResolver host_resolver_;
9052 const HostPortPair host_port_;
9053};
9054
9055TEST_F(HttpNetworkTransactionTest,
9056 UseIPConnectionPoolingWithHostCacheExpiration) {
9057 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349058 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469059
9060 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9061 SessionDependencies session_deps;
9062 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9063 net::HttpNetworkSession::Params params;
9064 params.client_socket_factory = &session_deps.socket_factory;
9065 params.host_resolver = &host_resolver;
9066 params.cert_verifier = session_deps.cert_verifier.get();
9067 params.proxy_service = session_deps.proxy_service.get();
9068 params.ssl_config_service = session_deps.ssl_config_service;
9069 params.http_auth_handler_factory =
9070 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539071 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469072 params.net_log = session_deps.net_log;
9073 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269074 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9075 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469076
9077 SSLSocketDataProvider ssl(true, OK);
9078 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:209079 ssl.next_proto = "spdy/2.1";
[email protected]e3ceb682011-06-28 23:55:469080 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:209081 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]e3ceb682011-06-28 23:55:469082 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9083
9084 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9085 "https://www.google.com", false, 1, LOWEST));
9086 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9087 "https://www.gmail.com", false, 3, LOWEST));
9088 MockWrite spdy_writes[] = {
9089 CreateMockWrite(*host1_req, 1),
9090 CreateMockWrite(*host2_req, 4),
9091 };
9092 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9093 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9094 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9095 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9096 MockRead spdy_reads[] = {
9097 CreateMockRead(*host1_resp, 2),
9098 CreateMockRead(*host1_resp_body, 3),
9099 CreateMockRead(*host2_resp, 5),
9100 CreateMockRead(*host2_resp_body, 6),
9101 MockRead(true, 0, 7),
9102 };
9103
[email protected]a1595312012-01-22 03:25:049104 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:469105 new OrderedSocketData(
9106 spdy_reads, arraysize(spdy_reads),
9107 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:049108 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:469109
[email protected]aa22b242011-11-16 18:58:299110 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469111 HttpRequestInfo request1;
9112 request1.method = "GET";
9113 request1.url = GURL("https://www.google.com/");
9114 request1.load_flags = 0;
9115 HttpNetworkTransaction trans1(session);
9116
[email protected]49639fa2011-12-20 23:22:419117 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469118 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419119 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469120
9121 const HttpResponseInfo* response = trans1.GetResponseInfo();
9122 ASSERT_TRUE(response != NULL);
9123 ASSERT_TRUE(response->headers != NULL);
9124 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9125
9126 std::string response_data;
9127 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9128 EXPECT_EQ("hello!", response_data);
9129
9130 // Preload cache entries into HostCache.
9131 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9132 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299133 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479134 BoundNetLog());
9135 EXPECT_EQ(ERR_IO_PENDING, rv);
9136 rv = callback.WaitForResult();
9137 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469138
9139 HttpRequestInfo request2;
9140 request2.method = "GET";
9141 request2.url = GURL("https://www.gmail.com/");
9142 request2.load_flags = 0;
9143 HttpNetworkTransaction trans2(session);
9144
[email protected]5c288bc2011-07-26 15:12:059145 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9146 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9147 // (www.google.com, 443).
9148 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9149 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049150
[email protected]49639fa2011-12-20 23:22:419151 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469152 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419153 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469154
9155 response = trans2.GetResponseInfo();
9156 ASSERT_TRUE(response != NULL);
9157 ASSERT_TRUE(response->headers != NULL);
9158 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9159 EXPECT_TRUE(response->was_fetched_via_spdy);
9160 EXPECT_TRUE(response->was_npn_negotiated);
9161 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9162 EXPECT_EQ("hello!", response_data);
9163
[email protected]5285d972011-10-18 18:56:349164 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469165 HttpStreamFactory::set_use_alternate_protocols(false);
9166}
9167
[email protected]5a60c8b2011-10-19 20:14:299168TEST_F(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
9169 MockRead data_reads1[] = {
9170 MockRead(false, ERR_PIPELINE_EVICTION),
9171 };
9172 MockRead data_reads2[] = {
9173 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9174 MockRead("hello world"),
9175 MockRead(false, OK),
9176 };
9177 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
9178 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
9179 StaticSocketDataProvider* data[] = { &data1, &data2 };
9180
9181 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9182
9183 EXPECT_EQ(OK, out.rv);
9184 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9185 EXPECT_EQ("hello world", out.response_data);
9186}
9187
9188TEST_F(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
9189 MockWrite data_writes1[] = {
9190 MockWrite(false, ERR_PIPELINE_EVICTION),
9191 };
9192 MockWrite data_writes2[] = {
9193 MockWrite("GET / HTTP/1.1\r\n"
9194 "Host: www.google.com\r\n"
9195 "Connection: keep-alive\r\n\r\n"),
9196 };
9197 MockRead data_reads2[] = {
9198 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9199 MockRead("hello world"),
9200 MockRead(false, OK),
9201 };
9202 StaticSocketDataProvider data1(NULL, 0,
9203 data_writes1, arraysize(data_writes1));
9204 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9205 data_writes2, arraysize(data_writes2));
9206 StaticSocketDataProvider* data[] = { &data1, &data2 };
9207
9208 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9209
9210 EXPECT_EQ(OK, out.rv);
9211 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9212 EXPECT_EQ("hello world", out.response_data);
9213}
9214
[email protected]89ceba9a2009-03-21 03:46:069215} // namespace net