blob: 94deb89045ac349b429f07c15b81dadc8cb249ef [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);
2159 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202160 ssl.next_proto = "spdy/2.1";
[email protected]7642b5ae2010-09-01 20:55:172161 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202162 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]7642b5ae2010-09-01 20:55:172163 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2164
[email protected]49639fa2011-12-20 23:22:412165 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:172166
[email protected]0b0bf032010-09-21 18:08:502167 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2168
[email protected]49639fa2011-12-20 23:22:412169 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:172170 EXPECT_EQ(ERR_IO_PENDING, rv);
2171
2172 rv = callback1.WaitForResult();
2173 EXPECT_EQ(OK, rv);
2174
2175 const HttpResponseInfo* response = trans->GetResponseInfo();
2176 ASSERT_TRUE(response != NULL);
2177 ASSERT_TRUE(response->headers != NULL);
2178 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2179
2180 std::string response_data;
2181 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2182 EXPECT_EQ(net::kUploadData, response_data);
2183}
2184
[email protected]dc7bd1c52010-11-12 00:01:132185// Test a SPDY get through an HTTPS Proxy.
2186TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272187 HttpRequestInfo request;
2188 request.method = "GET";
2189 request.url = GURL("http://www.google.com/");
2190 request.load_flags = 0;
2191
[email protected]79cb5c12011-09-12 13:12:042192 // Configure against https proxy server "myproxy:70".
[email protected]dc7bd1c52010-11-12 00:01:132193 SessionDependencies session_deps(
[email protected]79cb5c12011-09-12 13:12:042194 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]dc7bd1c52010-11-12 00:01:132195 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2196 session_deps.net_log = log.bound().net_log();
2197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2198
[email protected]dc7bd1c52010-11-12 00:01:132199 // The first request will be a bare GET, the second request will be a
2200 // GET with a Proxy-Authorization header.
2201 scoped_ptr<spdy::SpdyFrame> req_get(
2202 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2203 const char* const kExtraAuthorizationHeaders[] = {
2204 "proxy-authorization",
2205 "Basic Zm9vOmJhcg==",
2206 };
2207 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2208 ConstructSpdyGet(
2209 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2210 false, 3, LOWEST, false));
2211 MockWrite spdy_writes[] = {
2212 CreateMockWrite(*req_get, 1),
2213 CreateMockWrite(*req_get_authorization, 4),
2214 };
2215
2216 // The first response is a 407 proxy authentication challenge, and the second
2217 // response will be a 200 response since the second request includes a valid
2218 // Authorization header.
2219 const char* const kExtraAuthenticationHeaders[] = {
2220 "Proxy-Authenticate",
2221 "Basic realm=\"MyRealm1\""
2222 };
2223 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2224 ConstructSpdySynReplyError(
2225 "407 Proxy Authentication Required",
2226 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2227 1));
2228 scoped_ptr<spdy::SpdyFrame> body_authentication(
2229 ConstructSpdyBodyFrame(1, true));
2230 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2231 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2232 MockRead spdy_reads[] = {
2233 CreateMockRead(*resp_authentication, 2),
2234 CreateMockRead(*body_authentication, 3),
2235 CreateMockRead(*resp_data, 5),
2236 CreateMockRead(*body_data, 6),
2237 MockRead(true, 0, 7),
2238 };
2239
[email protected]a1595312012-01-22 03:25:042240 scoped_ptr<OrderedSocketData> data(
[email protected]dc7bd1c52010-11-12 00:01:132241 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2242 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042243 session_deps.socket_factory.AddSocketDataProvider(data.get());
[email protected]dc7bd1c52010-11-12 00:01:132244
2245 SSLSocketDataProvider ssl(true, OK);
2246 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202247 ssl.next_proto = "spdy/2.1";
[email protected]dc7bd1c52010-11-12 00:01:132248 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202249 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]dc7bd1c52010-11-12 00:01:132250 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2251
[email protected]49639fa2011-12-20 23:22:412252 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:132253
2254 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2255
[email protected]49639fa2011-12-20 23:22:412256 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:132257 EXPECT_EQ(ERR_IO_PENDING, rv);
2258
2259 rv = callback1.WaitForResult();
2260 EXPECT_EQ(OK, rv);
2261
2262 const HttpResponseInfo* const response = trans->GetResponseInfo();
2263
2264 ASSERT_TRUE(response != NULL);
2265 ASSERT_TRUE(response->headers != NULL);
2266 EXPECT_EQ(407, response->headers->response_code());
2267 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:042268 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:132269
[email protected]49639fa2011-12-20 23:22:412270 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:132271
[email protected]49639fa2011-12-20 23:22:412272 rv = trans->RestartWithAuth(
2273 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:132274 EXPECT_EQ(ERR_IO_PENDING, rv);
2275
2276 rv = callback2.WaitForResult();
2277 EXPECT_EQ(OK, rv);
2278
2279 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2280
2281 ASSERT_TRUE(response_restart != NULL);
2282 ASSERT_TRUE(response_restart->headers != NULL);
2283 EXPECT_EQ(200, response_restart->headers->response_code());
2284 // The password prompt info should not be set.
2285 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2286}
2287
[email protected]d9da5fe2010-10-13 22:37:162288// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2289TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272290 HttpRequestInfo request;
2291 request.method = "GET";
2292 request.url = GURL("https://www.google.com/");
2293 request.load_flags = 0;
2294
[email protected]d9da5fe2010-10-13 22:37:162295 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112296 SessionDependencies session_deps(ProxyService::CreateFixed(
2297 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162298 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2299 session_deps.net_log = log.bound().net_log();
2300 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2301
2302 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2303
[email protected]d9da5fe2010-10-13 22:37:162304 // CONNECT to www.google.com:443 via SPDY
2305 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2306 // fetch https://www.google.com/ via HTTP
2307
2308 const char get[] = "GET / HTTP/1.1\r\n"
2309 "Host: www.google.com\r\n"
2310 "Connection: keep-alive\r\n\r\n";
2311 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2312 ConstructSpdyBodyFrame(1, get, strlen(get), false));
[email protected]d9da5fe2010-10-13 22:37:162313 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2314 const char resp[] = "HTTP/1.1 200 OK\r\n"
2315 "Content-Length: 10\r\n\r\n";
[email protected]d9da5fe2010-10-13 22:37:162316 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2317 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2318 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2319 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]8d2f7012012-02-16 00:08:042320 scoped_ptr<spdy::SpdyFrame> window_update(
2321 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2322
2323 MockWrite spdy_writes[] = {
2324 CreateMockWrite(*connect, 1),
2325 CreateMockWrite(*wrapped_get, 3),
2326 CreateMockWrite(*window_update, 5)
2327 };
2328
[email protected]d9da5fe2010-10-13 22:37:162329 MockRead spdy_reads[] = {
2330 CreateMockRead(*conn_resp, 2, true),
2331 CreateMockRead(*wrapped_get_resp, 4, true),
[email protected]d9da5fe2010-10-13 22:37:162332 CreateMockRead(*wrapped_body, 6, true),
[email protected]8d2f7012012-02-16 00:08:042333 CreateMockRead(*wrapped_body, 7, true),
2334 MockRead(true, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:162335 };
2336
[email protected]a1595312012-01-22 03:25:042337 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162338 new OrderedSocketData(
2339 spdy_reads, arraysize(spdy_reads),
2340 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042341 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162342
2343 SSLSocketDataProvider ssl(true, OK);
2344 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202345 ssl.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162346 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202347 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162348 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2349 SSLSocketDataProvider ssl2(true, OK);
2350 ssl2.was_npn_negotiated = false;
[email protected]c30bcce2011-12-20 17:50:512351 ssl2.protocol_negotiated = SSLClientSocket::kProtoUnknown;
[email protected]d9da5fe2010-10-13 22:37:162352 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2353
[email protected]49639fa2011-12-20 23:22:412354 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162355
[email protected]49639fa2011-12-20 23:22:412356 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162357 EXPECT_EQ(ERR_IO_PENDING, rv);
2358
2359 rv = callback1.WaitForResult();
2360 EXPECT_EQ(OK, rv);
2361
2362 const HttpResponseInfo* response = trans->GetResponseInfo();
2363 ASSERT_TRUE(response != NULL);
2364 ASSERT_TRUE(response->headers != NULL);
2365 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2366
2367 std::string response_data;
2368 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2369 EXPECT_EQ("1234567890", response_data);
2370}
2371
2372// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2373TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272374 HttpRequestInfo request;
2375 request.method = "GET";
2376 request.url = GURL("https://www.google.com/");
2377 request.load_flags = 0;
2378
[email protected]d9da5fe2010-10-13 22:37:162379 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112380 SessionDependencies session_deps(ProxyService::CreateFixed(
2381 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162382 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2383 session_deps.net_log = log.bound().net_log();
2384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2385
2386 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2387
[email protected]d9da5fe2010-10-13 22:37:162388 // CONNECT to www.google.com:443 via SPDY
2389 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2390 // fetch https://www.google.com/ via SPDY
2391 const char* const kMyUrl = "https://www.google.com/";
2392 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2393 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
[email protected]d9da5fe2010-10-13 22:37:162394 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2395 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2396 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2397 ConstructWrappedSpdyFrame(get_resp, 1));
2398 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2399 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
[email protected]8d2f7012012-02-16 00:08:042400 scoped_ptr<spdy::SpdyFrame> window_update_get_resp(
2401 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2402 scoped_ptr<spdy::SpdyFrame> window_update_body(
2403 ConstructSpdyWindowUpdate(1, wrapped_body->length()));
2404
2405 MockWrite spdy_writes[] = {
2406 CreateMockWrite(*connect, 1),
2407 CreateMockWrite(*wrapped_get, 3),
2408 CreateMockWrite(*window_update_get_resp, 5),
2409 CreateMockWrite(*window_update_body, 7),
2410 };
2411
[email protected]d9da5fe2010-10-13 22:37:162412 MockRead spdy_reads[] = {
2413 CreateMockRead(*conn_resp, 2, true),
2414 CreateMockRead(*wrapped_get_resp, 4, true),
[email protected]8d2f7012012-02-16 00:08:042415 CreateMockRead(*wrapped_body, 6, true),
2416 MockRead(true, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:162417 };
2418
[email protected]a1595312012-01-22 03:25:042419 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162420 new OrderedSocketData(
2421 spdy_reads, arraysize(spdy_reads),
2422 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042423 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162424
2425 SSLSocketDataProvider ssl(true, OK);
2426 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202427 ssl.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162428 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202429 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162430 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2431 SSLSocketDataProvider ssl2(true, OK);
2432 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202433 ssl2.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162434 ssl2.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202435 ssl2.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162436 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2437
[email protected]49639fa2011-12-20 23:22:412438 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162439
[email protected]49639fa2011-12-20 23:22:412440 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162441 EXPECT_EQ(ERR_IO_PENDING, rv);
2442
2443 rv = callback1.WaitForResult();
2444 EXPECT_EQ(OK, rv);
2445
2446 const HttpResponseInfo* response = trans->GetResponseInfo();
2447 ASSERT_TRUE(response != NULL);
2448 ASSERT_TRUE(response->headers != NULL);
2449 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2450
2451 std::string response_data;
2452 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2453 EXPECT_EQ(net::kUploadData, response_data);
2454}
2455
2456// Test a SPDY CONNECT failure through an HTTPS Proxy.
2457TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272458 HttpRequestInfo request;
2459 request.method = "GET";
2460 request.url = GURL("https://www.google.com/");
2461 request.load_flags = 0;
2462
[email protected]d9da5fe2010-10-13 22:37:162463 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112464 SessionDependencies session_deps(ProxyService::CreateFixed(
2465 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162466 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2467 session_deps.net_log = log.bound().net_log();
2468 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2469
2470 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2471
[email protected]d9da5fe2010-10-13 22:37:162472 // CONNECT to www.google.com:443 via SPDY
2473 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2474 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2475
2476 MockWrite spdy_writes[] = {
2477 CreateMockWrite(*connect, 1),
2478 CreateMockWrite(*get, 3),
2479 };
2480
2481 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2482 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2483 MockRead spdy_reads[] = {
2484 CreateMockRead(*resp, 2, true),
2485 MockRead(true, 0, 4),
2486 };
2487
[email protected]a1595312012-01-22 03:25:042488 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162489 new OrderedSocketData(
2490 spdy_reads, arraysize(spdy_reads),
2491 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042492 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162493
2494 SSLSocketDataProvider ssl(true, OK);
2495 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202496 ssl.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162497 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202498 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162499 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2500 SSLSocketDataProvider ssl2(true, OK);
2501 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202502 ssl2.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162503 ssl2.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202504 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162505 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2506
[email protected]49639fa2011-12-20 23:22:412507 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162508
[email protected]49639fa2011-12-20 23:22:412509 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162510 EXPECT_EQ(ERR_IO_PENDING, rv);
2511
2512 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292513 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162514
2515 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502516 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:292517 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162518}
2519
[email protected]2df19bb2010-08-25 20:13:462520// Test the challenge-response-retry sequence through an HTTPS Proxy
2521TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462522 HttpRequestInfo request;
2523 request.method = "GET";
2524 request.url = GURL("http://www.google.com/");
2525 // when the no authentication data flag is set.
2526 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2527
[email protected]79cb5c12011-09-12 13:12:042528 // Configure against https proxy server "myproxy:70".
2529 SessionDependencies session_deps(
2530 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]cb9bf6ca2011-01-28 13:15:272531 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2532 session_deps.net_log = log.bound().net_log();
2533 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2534
[email protected]2df19bb2010-08-25 20:13:462535 // Since we have proxy, should use full url
2536 MockWrite data_writes1[] = {
2537 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2538 "Host: www.google.com\r\n"
2539 "Proxy-Connection: keep-alive\r\n\r\n"),
2540
2541 // After calling trans->RestartWithAuth(), this is the request we should
2542 // be issuing -- the final header line contains the credentials.
2543 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2544 "Host: www.google.com\r\n"
2545 "Proxy-Connection: keep-alive\r\n"
2546 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2547 };
2548
2549 // The proxy responds to the GET with a 407, using a persistent
2550 // connection.
2551 MockRead data_reads1[] = {
2552 // No credentials.
2553 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2554 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2555 MockRead("Proxy-Connection: keep-alive\r\n"),
2556 MockRead("Content-Length: 0\r\n\r\n"),
2557
2558 MockRead("HTTP/1.1 200 OK\r\n"),
2559 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2560 MockRead("Content-Length: 100\r\n\r\n"),
2561 MockRead(false, OK),
2562 };
2563
2564 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2565 data_writes1, arraysize(data_writes1));
2566 session_deps.socket_factory.AddSocketDataProvider(&data1);
2567 SSLSocketDataProvider ssl(true, OK);
2568 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2569
[email protected]49639fa2011-12-20 23:22:412570 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462571
[email protected]0b0bf032010-09-21 18:08:502572 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2573
[email protected]49639fa2011-12-20 23:22:412574 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:462575 EXPECT_EQ(ERR_IO_PENDING, rv);
2576
2577 rv = callback1.WaitForResult();
2578 EXPECT_EQ(OK, rv);
2579
2580 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502581 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042582 ASSERT_FALSE(response->headers == NULL);
[email protected]2df19bb2010-08-25 20:13:462583 EXPECT_EQ(407, response->headers->response_code());
2584 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042585 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:462586
[email protected]49639fa2011-12-20 23:22:412587 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:462588
[email protected]49639fa2011-12-20 23:22:412589 rv = trans->RestartWithAuth(
2590 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:462591 EXPECT_EQ(ERR_IO_PENDING, rv);
2592
2593 rv = callback2.WaitForResult();
2594 EXPECT_EQ(OK, rv);
2595
2596 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502597 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462598
2599 EXPECT_TRUE(response->headers->IsKeepAlive());
2600 EXPECT_EQ(200, response->headers->response_code());
2601 EXPECT_EQ(100, response->headers->GetContentLength());
2602 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2603
2604 // The password prompt info should not be set.
2605 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2606}
2607
[email protected]ff007e162009-05-23 09:13:152608void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082609 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422610 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082611 request.method = "GET";
2612 request.url = GURL("https://www.google.com/");
2613 request.load_flags = 0;
2614
[email protected]cb9bf6ca2011-01-28 13:15:272615 // Configure against proxy server "myproxy:70".
2616 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2617
2618 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2619
[email protected]c744cf22009-02-27 07:28:082620 // Since we have proxy, should try to establish tunnel.
2621 MockWrite data_writes[] = {
2622 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452623 "Host: www.google.com\r\n"
2624 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082625 };
2626
2627 MockRead data_reads[] = {
2628 status,
2629 MockRead("Content-Length: 10\r\n\r\n"),
2630 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422631 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082632 };
2633
[email protected]31a2bfe2010-02-09 08:03:392634 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2635 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592636 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082637
[email protected]49639fa2011-12-20 23:22:412638 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:082639
[email protected]0b0bf032010-09-21 18:08:502640 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2641
[email protected]49639fa2011-12-20 23:22:412642 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422643 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082644
2645 rv = callback.WaitForResult();
2646 EXPECT_EQ(expected_status, rv);
2647}
2648
[email protected]ff007e162009-05-23 09:13:152649void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082650 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422651 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082652}
2653
2654TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2655 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2656}
2657
2658TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2659 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2660}
2661
2662TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2663 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2664}
2665
2666TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2667 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2668}
2669
2670TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2671 ConnectStatusHelper(
2672 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2673}
2674
2675TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2676 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2677}
2678
2679TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2680 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2681}
2682
2683TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2684 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2685}
2686
2687TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2688 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2689}
2690
2691TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2692 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2693}
2694
2695TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2696 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2697}
2698
2699TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2700 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2701}
2702
2703TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2704 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2705}
2706
2707TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2708 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2709}
2710
2711TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2712 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2713}
2714
2715TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2716 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2717}
2718
2719TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2720 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2721}
2722
2723TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2724 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2725}
2726
2727TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2728 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2729}
2730
2731TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2732 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2733}
2734
2735TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2736 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2737}
2738
2739TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2740 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2741}
2742
2743TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2744 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2745}
2746
2747TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2748 ConnectStatusHelperWithExpectedStatus(
2749 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542750 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082751}
2752
2753TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2754 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2755}
2756
2757TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2758 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2759}
2760
2761TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2762 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2763}
2764
2765TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2766 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2767}
2768
2769TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2770 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2771}
2772
2773TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2774 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2775}
2776
2777TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2778 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2779}
2780
2781TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2782 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2783}
2784
2785TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2786 ConnectStatusHelper(
2787 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2788}
2789
2790TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2791 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2792}
2793
2794TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2795 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2796}
2797
2798TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2799 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2800}
2801
2802TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2803 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2804}
2805
2806TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2807 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2808}
2809
2810TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2811 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2812}
2813
2814TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2815 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2816}
2817
[email protected]038e9a32008-10-08 22:40:162818// Test the flow when both the proxy server AND origin server require
2819// authentication. Again, this uses basic auth for both since that is
2820// the simplest to mock.
2821TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272822 HttpRequestInfo request;
2823 request.method = "GET";
2824 request.url = GURL("http://www.google.com/");
2825 request.load_flags = 0;
2826
[email protected]81cdfcd2010-10-16 00:49:002827 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012828
[email protected]038e9a32008-10-08 22:40:162829 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422830 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432831 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162832
[email protected]f9ee6b52008-11-08 06:46:232833 MockWrite data_writes1[] = {
2834 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2835 "Host: www.google.com\r\n"
2836 "Proxy-Connection: keep-alive\r\n\r\n"),
2837 };
2838
[email protected]038e9a32008-10-08 22:40:162839 MockRead data_reads1[] = {
2840 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2841 // Give a couple authenticate options (only the middle one is actually
2842 // supported).
[email protected]22927ad2009-09-21 19:56:192843 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162844 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2845 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2846 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2847 // Large content-length -- won't matter, as connection will be reset.
2848 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422849 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162850 };
2851
2852 // After calling trans->RestartWithAuth() the first time, this is the
2853 // request we should be issuing -- the final header line contains the
2854 // proxy's credentials.
2855 MockWrite data_writes2[] = {
2856 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2857 "Host: www.google.com\r\n"
2858 "Proxy-Connection: keep-alive\r\n"
2859 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2860 };
2861
2862 // Now the proxy server lets the request pass through to origin server.
2863 // The origin server responds with a 401.
2864 MockRead data_reads2[] = {
2865 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2866 // Note: We are using the same realm-name as the proxy server. This is
2867 // completely valid, as realms are unique across hosts.
2868 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2869 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2870 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422871 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162872 };
2873
2874 // After calling trans->RestartWithAuth() the second time, we should send
2875 // the credentials for both the proxy and origin server.
2876 MockWrite data_writes3[] = {
2877 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2878 "Host: www.google.com\r\n"
2879 "Proxy-Connection: keep-alive\r\n"
2880 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2881 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2882 };
2883
2884 // Lastly we get the desired content.
2885 MockRead data_reads3[] = {
2886 MockRead("HTTP/1.0 200 OK\r\n"),
2887 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2888 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422889 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162890 };
2891
[email protected]31a2bfe2010-02-09 08:03:392892 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2893 data_writes1, arraysize(data_writes1));
2894 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2895 data_writes2, arraysize(data_writes2));
2896 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2897 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592898 session_deps.socket_factory.AddSocketDataProvider(&data1);
2899 session_deps.socket_factory.AddSocketDataProvider(&data2);
2900 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162901
[email protected]49639fa2011-12-20 23:22:412902 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162903
[email protected]49639fa2011-12-20 23:22:412904 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422905 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162906
2907 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422908 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162909
[email protected]1c773ea12009-04-28 19:58:422910 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502911 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042912 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162913
[email protected]49639fa2011-12-20 23:22:412914 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162915
[email protected]49639fa2011-12-20 23:22:412916 rv = trans->RestartWithAuth(
2917 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422918 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162919
2920 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422921 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162922
2923 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502924 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042925 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162926
[email protected]49639fa2011-12-20 23:22:412927 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:162928
[email protected]49639fa2011-12-20 23:22:412929 rv = trans->RestartWithAuth(
2930 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:422931 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162932
2933 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422934 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162935
2936 response = trans->GetResponseInfo();
2937 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2938 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162939}
[email protected]4ddaf2502008-10-23 18:26:192940
[email protected]ea9dc9a2009-09-05 00:43:322941// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2942// can't hook into its internals to cause it to generate predictable NTLM
2943// authorization headers.
2944#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292945// The NTLM authentication unit tests were generated by capturing the HTTP
2946// requests and responses using Fiddler 2 and inspecting the generated random
2947// bytes in the debugger.
2948
2949// Enter the correct password and authenticate successfully.
2950TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422951 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242952 request.method = "GET";
2953 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2954 request.load_flags = 0;
2955
[email protected]cb9bf6ca2011-01-28 13:15:272956 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2957 MockGetHostName);
2958 SessionDependencies session_deps;
2959 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2960
[email protected]3f918782009-02-28 01:29:242961 MockWrite data_writes1[] = {
2962 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2963 "Host: 172.22.68.17\r\n"
2964 "Connection: keep-alive\r\n\r\n"),
2965 };
2966
2967 MockRead data_reads1[] = {
2968 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042969 // Negotiate and NTLM are often requested together. However, we only want
2970 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2971 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242972 MockRead("WWW-Authenticate: NTLM\r\n"),
2973 MockRead("Connection: close\r\n"),
2974 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362975 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242976 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422977 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242978 };
2979
2980 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222981 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242982 // request we should be issuing -- the final header line contains a Type
2983 // 1 message.
2984 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2985 "Host: 172.22.68.17\r\n"
2986 "Connection: keep-alive\r\n"
2987 "Authorization: NTLM "
2988 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2989
2990 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2991 // (the credentials for the origin server). The second request continues
2992 // on the same connection.
2993 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2994 "Host: 172.22.68.17\r\n"
2995 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292996 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2997 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2998 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2999 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
3000 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:243001 };
3002
3003 MockRead data_reads2[] = {
3004 // The origin server responds with a Type 2 message.
3005 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3006 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:293007 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:243008 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3009 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3010 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3011 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3012 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3013 "BtAAAAAAA=\r\n"),
3014 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363015 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:243016 MockRead("You are not authorized to view this page\r\n"),
3017
3018 // Lastly we get the desired content.
3019 MockRead("HTTP/1.1 200 OK\r\n"),
3020 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3021 MockRead("Content-Length: 13\r\n\r\n"),
3022 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423023 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:243024 };
3025
[email protected]31a2bfe2010-02-09 08:03:393026 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3027 data_writes1, arraysize(data_writes1));
3028 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3029 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593030 session_deps.socket_factory.AddSocketDataProvider(&data1);
3031 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:243032
[email protected]49639fa2011-12-20 23:22:413033 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:243034
[email protected]0b0bf032010-09-21 18:08:503035 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3036
[email protected]49639fa2011-12-20 23:22:413037 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423038 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243039
3040 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423041 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243042
[email protected]0757e7702009-03-27 04:00:223043 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3044
[email protected]1c773ea12009-04-28 19:58:423045 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043046 ASSERT_FALSE(response == NULL);
3047 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:243048
[email protected]49639fa2011-12-20 23:22:413049 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:253050
[email protected]f3cf9802011-10-28 18:44:583051 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413052 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:253053 EXPECT_EQ(ERR_IO_PENDING, rv);
3054
3055 rv = callback2.WaitForResult();
3056 EXPECT_EQ(OK, rv);
3057
3058 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3059
3060 response = trans->GetResponseInfo();
3061 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:253062 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3063
[email protected]49639fa2011-12-20 23:22:413064 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:243065
[email protected]49639fa2011-12-20 23:22:413066 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423067 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243068
[email protected]0757e7702009-03-27 04:00:223069 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423070 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243071
3072 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503073 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:243074 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3075 EXPECT_EQ(13, response->headers->GetContentLength());
3076}
3077
[email protected]385a4672009-03-11 22:21:293078// Enter a wrong password, and then the correct one.
3079TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:423080 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:293081 request.method = "GET";
3082 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3083 request.load_flags = 0;
3084
[email protected]cb9bf6ca2011-01-28 13:15:273085 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3086 MockGetHostName);
3087 SessionDependencies session_deps;
3088 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3089
[email protected]385a4672009-03-11 22:21:293090 MockWrite data_writes1[] = {
3091 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3092 "Host: 172.22.68.17\r\n"
3093 "Connection: keep-alive\r\n\r\n"),
3094 };
3095
3096 MockRead data_reads1[] = {
3097 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:043098 // Negotiate and NTLM are often requested together. However, we only want
3099 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3100 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:293101 MockRead("WWW-Authenticate: NTLM\r\n"),
3102 MockRead("Connection: close\r\n"),
3103 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363104 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293105 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423106 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293107 };
3108
3109 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:223110 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293111 // request we should be issuing -- the final header line contains a Type
3112 // 1 message.
3113 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3114 "Host: 172.22.68.17\r\n"
3115 "Connection: keep-alive\r\n"
3116 "Authorization: NTLM "
3117 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3118
3119 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3120 // (the credentials for the origin server). The second request continues
3121 // on the same connection.
3122 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3123 "Host: 172.22.68.17\r\n"
3124 "Connection: keep-alive\r\n"
3125 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3126 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3127 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
3128 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
3129 "4Ww7b7E=\r\n\r\n"),
3130 };
3131
3132 MockRead data_reads2[] = {
3133 // The origin server responds with a Type 2 message.
3134 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3135 MockRead("WWW-Authenticate: NTLM "
3136 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
3137 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3138 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3139 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3140 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3141 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3142 "BtAAAAAAA=\r\n"),
3143 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363144 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293145 MockRead("You are not authorized to view this page\r\n"),
3146
3147 // Wrong password.
3148 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:293149 MockRead("WWW-Authenticate: NTLM\r\n"),
3150 MockRead("Connection: close\r\n"),
3151 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363152 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293153 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423154 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293155 };
3156
3157 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223158 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293159 // request we should be issuing -- the final header line contains a Type
3160 // 1 message.
3161 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3162 "Host: 172.22.68.17\r\n"
3163 "Connection: keep-alive\r\n"
3164 "Authorization: NTLM "
3165 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3166
3167 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3168 // (the credentials for the origin server). The second request continues
3169 // on the same connection.
3170 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3171 "Host: 172.22.68.17\r\n"
3172 "Connection: keep-alive\r\n"
3173 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3174 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3175 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3176 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3177 "+4MUm7c=\r\n\r\n"),
3178 };
3179
3180 MockRead data_reads3[] = {
3181 // The origin server responds with a Type 2 message.
3182 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3183 MockRead("WWW-Authenticate: NTLM "
3184 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3185 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3186 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3187 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3188 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3189 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3190 "BtAAAAAAA=\r\n"),
3191 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363192 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293193 MockRead("You are not authorized to view this page\r\n"),
3194
3195 // Lastly we get the desired content.
3196 MockRead("HTTP/1.1 200 OK\r\n"),
3197 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3198 MockRead("Content-Length: 13\r\n\r\n"),
3199 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423200 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293201 };
3202
[email protected]31a2bfe2010-02-09 08:03:393203 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3204 data_writes1, arraysize(data_writes1));
3205 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3206 data_writes2, arraysize(data_writes2));
3207 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3208 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593209 session_deps.socket_factory.AddSocketDataProvider(&data1);
3210 session_deps.socket_factory.AddSocketDataProvider(&data2);
3211 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293212
[email protected]49639fa2011-12-20 23:22:413213 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:293214
[email protected]0b0bf032010-09-21 18:08:503215 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3216
[email protected]49639fa2011-12-20 23:22:413217 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423218 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293219
3220 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423221 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293222
[email protected]0757e7702009-03-27 04:00:223223 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293224
[email protected]1c773ea12009-04-28 19:58:423225 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503226 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043227 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:293228
[email protected]49639fa2011-12-20 23:22:413229 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293230
[email protected]0757e7702009-03-27 04:00:223231 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:583232 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:413233 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423234 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293235
[email protected]10af5fe72011-01-31 16:17:253236 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423237 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293238
[email protected]0757e7702009-03-27 04:00:223239 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:413240 TestCompletionCallback callback3;
3241 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423242 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253243 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423244 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223245 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3246
3247 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043248 ASSERT_FALSE(response == NULL);
3249 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:223250
[email protected]49639fa2011-12-20 23:22:413251 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223252
3253 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:583254 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413255 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:253256 EXPECT_EQ(ERR_IO_PENDING, rv);
3257
3258 rv = callback4.WaitForResult();
3259 EXPECT_EQ(OK, rv);
3260
3261 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3262
[email protected]49639fa2011-12-20 23:22:413263 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:253264
3265 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:413266 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:423267 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223268
3269 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423270 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223271
[email protected]385a4672009-03-11 22:21:293272 response = trans->GetResponseInfo();
3273 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3274 EXPECT_EQ(13, response->headers->GetContentLength());
3275}
[email protected]ea9dc9a2009-09-05 00:43:323276#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293277
[email protected]4ddaf2502008-10-23 18:26:193278// Test reading a server response which has only headers, and no body.
3279// After some maximum number of bytes is consumed, the transaction should
3280// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3281TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423282 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193283 request.method = "GET";
3284 request.url = GURL("http://www.google.com/");
3285 request.load_flags = 0;
3286
[email protected]cb9bf6ca2011-01-28 13:15:273287 SessionDependencies session_deps;
3288 scoped_ptr<HttpTransaction> trans(
3289 new HttpNetworkTransaction(CreateSession(&session_deps)));
3290
[email protected]b75b7b2f2009-10-06 00:54:533291 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433292 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533293 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193294
3295 MockRead data_reads[] = {
3296 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433297 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193298 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423299 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193300 };
[email protected]31a2bfe2010-02-09 08:03:393301 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593302 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193303
[email protected]49639fa2011-12-20 23:22:413304 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:193305
[email protected]49639fa2011-12-20 23:22:413306 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423307 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193308
3309 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423310 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193311
[email protected]1c773ea12009-04-28 19:58:423312 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193313 EXPECT_TRUE(response == NULL);
3314}
[email protected]f4e426b2008-11-05 00:24:493315
3316// Make sure that we don't try to reuse a TCPClientSocket when failing to
3317// establish tunnel.
3318// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283319TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273320 HttpRequestInfo request;
3321 request.method = "GET";
3322 request.url = GURL("https://www.google.com/");
3323 request.load_flags = 0;
3324
[email protected]f4e426b2008-11-05 00:24:493325 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003326 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013327
[email protected]228ff742009-06-05 01:19:593328 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493329
[email protected]5695b8c2009-09-30 21:36:433330 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493331
[email protected]f4e426b2008-11-05 00:24:493332 // Since we have proxy, should try to establish tunnel.
3333 MockWrite data_writes1[] = {
3334 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453335 "Host: www.google.com\r\n"
3336 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493337 };
3338
[email protected]77848d12008-11-14 00:00:223339 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493340 // connection. Usually a proxy would return 501 (not implemented),
3341 // or 200 (tunnel established).
3342 MockRead data_reads1[] = {
3343 MockRead("HTTP/1.1 404 Not Found\r\n"),
3344 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423345 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493346 };
3347
[email protected]31a2bfe2010-02-09 08:03:393348 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3349 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593350 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493351
[email protected]49639fa2011-12-20 23:22:413352 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:493353
[email protected]49639fa2011-12-20 23:22:413354 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423355 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493356
3357 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423358 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493359
[email protected]1c773ea12009-04-28 19:58:423360 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083361 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493362
[email protected]b4404c02009-04-10 16:38:523363 // Empty the current queue. This is necessary because idle sockets are
3364 // added to the connection pool asynchronously with a PostTask.
3365 MessageLoop::current()->RunAllPending();
3366
[email protected]f4e426b2008-11-05 00:24:493367 // We now check to make sure the TCPClientSocket was not added back to
3368 // the pool.
[email protected]a42dbd142011-11-17 16:42:023369 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493370 trans.reset();
[email protected]b4404c02009-04-10 16:38:523371 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493372 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a42dbd142011-11-17 16:42:023373 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493374}
[email protected]372d34a2008-11-05 21:30:513375
[email protected]1b157c02009-04-21 01:55:403376// Make sure that we recycle a socket after reading all of the response body.
3377TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423378 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403379 request.method = "GET";
3380 request.url = GURL("http://www.google.com/");
3381 request.load_flags = 0;
3382
[email protected]cb9bf6ca2011-01-28 13:15:273383 SessionDependencies session_deps;
3384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3385
3386 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3387
[email protected]1b157c02009-04-21 01:55:403388 MockRead data_reads[] = {
3389 // A part of the response body is received with the response headers.
3390 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3391 // The rest of the response body is received in two parts.
3392 MockRead("lo"),
3393 MockRead(" world"),
3394 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423395 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403396 };
3397
[email protected]31a2bfe2010-02-09 08:03:393398 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593399 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403400
[email protected]49639fa2011-12-20 23:22:413401 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:403402
[email protected]49639fa2011-12-20 23:22:413403 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423404 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403405
3406 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423407 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403408
[email protected]1c773ea12009-04-28 19:58:423409 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503410 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:403411
3412 EXPECT_TRUE(response->headers != NULL);
3413 std::string status_line = response->headers->GetStatusLine();
3414 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3415
[email protected]a42dbd142011-11-17 16:42:023416 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403417
3418 std::string response_data;
3419 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423420 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403421 EXPECT_EQ("hello world", response_data);
3422
3423 // Empty the current queue. This is necessary because idle sockets are
3424 // added to the connection pool asynchronously with a PostTask.
3425 MessageLoop::current()->RunAllPending();
3426
3427 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023428 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403429}
3430
[email protected]76a505b2010-08-25 06:23:003431// Make sure that we recycle a SSL socket after reading all of the response
3432// body.
3433TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3434 SessionDependencies session_deps;
3435 HttpRequestInfo request;
3436 request.method = "GET";
3437 request.url = GURL("https://www.google.com/");
3438 request.load_flags = 0;
3439
3440 MockWrite data_writes[] = {
3441 MockWrite("GET / HTTP/1.1\r\n"
3442 "Host: www.google.com\r\n"
3443 "Connection: keep-alive\r\n\r\n"),
3444 };
3445
3446 MockRead data_reads[] = {
3447 MockRead("HTTP/1.1 200 OK\r\n"),
3448 MockRead("Content-Length: 11\r\n\r\n"),
3449 MockRead("hello world"),
3450 MockRead(false, OK),
3451 };
3452
3453 SSLSocketDataProvider ssl(true, OK);
3454 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3455
3456 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3457 data_writes, arraysize(data_writes));
3458 session_deps.socket_factory.AddSocketDataProvider(&data);
3459
[email protected]49639fa2011-12-20 23:22:413460 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003461
3462 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3463 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3464
[email protected]49639fa2011-12-20 23:22:413465 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003466
3467 EXPECT_EQ(ERR_IO_PENDING, rv);
3468 EXPECT_EQ(OK, callback.WaitForResult());
3469
3470 const HttpResponseInfo* response = trans->GetResponseInfo();
3471 ASSERT_TRUE(response != NULL);
3472 ASSERT_TRUE(response->headers != NULL);
3473 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3474
[email protected]a42dbd142011-11-17 16:42:023475 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003476
3477 std::string response_data;
3478 rv = ReadTransaction(trans.get(), &response_data);
3479 EXPECT_EQ(OK, rv);
3480 EXPECT_EQ("hello world", response_data);
3481
3482 // Empty the current queue. This is necessary because idle sockets are
3483 // added to the connection pool asynchronously with a PostTask.
3484 MessageLoop::current()->RunAllPending();
3485
3486 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023487 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003488}
3489
3490// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3491// from the pool and make sure that we recover okay.
3492TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3493 SessionDependencies session_deps;
3494 HttpRequestInfo request;
3495 request.method = "GET";
3496 request.url = GURL("https://www.google.com/");
3497 request.load_flags = 0;
3498
3499 MockWrite data_writes[] = {
3500 MockWrite("GET / HTTP/1.1\r\n"
3501 "Host: www.google.com\r\n"
3502 "Connection: keep-alive\r\n\r\n"),
3503 MockWrite("GET / HTTP/1.1\r\n"
3504 "Host: www.google.com\r\n"
3505 "Connection: keep-alive\r\n\r\n"),
3506 };
3507
3508 MockRead data_reads[] = {
3509 MockRead("HTTP/1.1 200 OK\r\n"),
3510 MockRead("Content-Length: 11\r\n\r\n"),
3511 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3512 MockRead("hello world"),
3513 MockRead(true, 0, 0) // EOF
3514 };
3515
3516 SSLSocketDataProvider ssl(true, OK);
3517 SSLSocketDataProvider ssl2(true, OK);
3518 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3519 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3520
3521 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3522 data_writes, arraysize(data_writes));
3523 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3524 data_writes, arraysize(data_writes));
3525 session_deps.socket_factory.AddSocketDataProvider(&data);
3526 session_deps.socket_factory.AddSocketDataProvider(&data2);
3527
[email protected]49639fa2011-12-20 23:22:413528 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003529
3530 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3531 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3532
[email protected]49639fa2011-12-20 23:22:413533 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003534
3535 EXPECT_EQ(ERR_IO_PENDING, rv);
3536 EXPECT_EQ(OK, callback.WaitForResult());
3537
3538 const HttpResponseInfo* response = trans->GetResponseInfo();
3539 ASSERT_TRUE(response != NULL);
3540 ASSERT_TRUE(response->headers != NULL);
3541 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3542
[email protected]a42dbd142011-11-17 16:42:023543 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003544
3545 std::string response_data;
3546 rv = ReadTransaction(trans.get(), &response_data);
3547 EXPECT_EQ(OK, rv);
3548 EXPECT_EQ("hello world", response_data);
3549
3550 // Empty the current queue. This is necessary because idle sockets are
3551 // added to the connection pool asynchronously with a PostTask.
3552 MessageLoop::current()->RunAllPending();
3553
3554 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023555 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003556
3557 // Now start the second transaction, which should reuse the previous socket.
3558
3559 trans.reset(new HttpNetworkTransaction(session));
3560
[email protected]49639fa2011-12-20 23:22:413561 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003562
3563 EXPECT_EQ(ERR_IO_PENDING, rv);
3564 EXPECT_EQ(OK, callback.WaitForResult());
3565
3566 response = trans->GetResponseInfo();
3567 ASSERT_TRUE(response != NULL);
3568 ASSERT_TRUE(response->headers != NULL);
3569 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3570
[email protected]a42dbd142011-11-17 16:42:023571 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003572
3573 rv = ReadTransaction(trans.get(), &response_data);
3574 EXPECT_EQ(OK, rv);
3575 EXPECT_EQ("hello world", response_data);
3576
3577 // Empty the current queue. This is necessary because idle sockets are
3578 // added to the connection pool asynchronously with a PostTask.
3579 MessageLoop::current()->RunAllPending();
3580
3581 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023582 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003583}
3584
[email protected]b4404c02009-04-10 16:38:523585// Make sure that we recycle a socket after a zero-length response.
3586// http://crbug.com/9880
3587TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423588 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523589 request.method = "GET";
3590 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3591 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3592 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3593 "rt=prt.2642,ol.2649,xjs.2951");
3594 request.load_flags = 0;
3595
[email protected]cb9bf6ca2011-01-28 13:15:273596 SessionDependencies session_deps;
3597 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3598
3599 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3600
[email protected]b4404c02009-04-10 16:38:523601 MockRead data_reads[] = {
3602 MockRead("HTTP/1.1 204 No Content\r\n"
3603 "Content-Length: 0\r\n"
3604 "Content-Type: text/html\r\n\r\n"),
3605 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423606 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523607 };
3608
[email protected]31a2bfe2010-02-09 08:03:393609 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593610 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523611
[email protected]49639fa2011-12-20 23:22:413612 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:523613
[email protected]49639fa2011-12-20 23:22:413614 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423615 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523616
3617 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423618 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523619
[email protected]1c773ea12009-04-28 19:58:423620 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503621 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:523622
3623 EXPECT_TRUE(response->headers != NULL);
3624 std::string status_line = response->headers->GetStatusLine();
3625 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3626
[email protected]a42dbd142011-11-17 16:42:023627 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523628
3629 std::string response_data;
3630 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423631 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523632 EXPECT_EQ("", response_data);
3633
3634 // Empty the current queue. This is necessary because idle sockets are
3635 // added to the connection pool asynchronously with a PostTask.
3636 MessageLoop::current()->RunAllPending();
3637
3638 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023639 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523640}
3641
[email protected]372d34a2008-11-05 21:30:513642TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423643 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513644 // Transaction 1: a GET request that succeeds. The socket is recycled
3645 // after use.
3646 request[0].method = "GET";
3647 request[0].url = GURL("http://www.google.com/");
3648 request[0].load_flags = 0;
3649 // Transaction 2: a POST request. Reuses the socket kept alive from
3650 // transaction 1. The first attempts fails when writing the POST data.
3651 // This causes the transaction to retry with a new socket. The second
3652 // attempt succeeds.
3653 request[1].method = "POST";
3654 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423655 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513656 request[1].upload_data->AppendBytes("foo", 3);
3657 request[1].load_flags = 0;
3658
[email protected]228ff742009-06-05 01:19:593659 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273660 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513661
3662 // The first socket is used for transaction 1 and the first attempt of
3663 // transaction 2.
3664
3665 // The response of transaction 1.
3666 MockRead data_reads1[] = {
3667 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3668 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423669 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513670 };
3671 // The mock write results of transaction 1 and the first attempt of
3672 // transaction 2.
3673 MockWrite data_writes1[] = {
3674 MockWrite(false, 64), // GET
3675 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423676 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513677 };
[email protected]31a2bfe2010-02-09 08:03:393678 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3679 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513680
3681 // The second socket is used for the second attempt of transaction 2.
3682
3683 // The response of transaction 2.
3684 MockRead data_reads2[] = {
3685 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3686 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423687 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513688 };
3689 // The mock write results of the second attempt of transaction 2.
3690 MockWrite data_writes2[] = {
3691 MockWrite(false, 93), // POST
3692 MockWrite(false, 3), // POST data
3693 };
[email protected]31a2bfe2010-02-09 08:03:393694 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3695 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513696
[email protected]5ecc992a42009-11-11 01:41:593697 session_deps.socket_factory.AddSocketDataProvider(&data1);
3698 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513699
3700 const char* kExpectedResponseData[] = {
3701 "hello world", "welcome"
3702 };
3703
3704 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423705 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433706 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513707
[email protected]49639fa2011-12-20 23:22:413708 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:513709
[email protected]49639fa2011-12-20 23:22:413710 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423711 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513712
3713 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423714 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513715
[email protected]1c773ea12009-04-28 19:58:423716 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503717 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:513718
3719 EXPECT_TRUE(response->headers != NULL);
3720 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3721
3722 std::string response_data;
3723 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423724 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513725 EXPECT_EQ(kExpectedResponseData[i], response_data);
3726 }
3727}
[email protected]f9ee6b52008-11-08 06:46:233728
3729// Test the request-challenge-retry sequence for basic auth when there is
3730// an identity in the URL. The request should be sent as normal, but when
[email protected]7b08ba62012-02-10 20:19:413731// it fails the identity from the URL is no longer used.
3732TEST_F(HttpNetworkTransactionTest, IgnoreAuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423733 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233734 request.method = "GET";
[email protected]a97cca42009-08-14 01:00:293735 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:413736 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:293737
[email protected]cb9bf6ca2011-01-28 13:15:273738 SessionDependencies session_deps;
3739 scoped_ptr<HttpTransaction> trans(
3740 new HttpNetworkTransaction(CreateSession(&session_deps)));
3741
[email protected]a97cca42009-08-14 01:00:293742 // The password contains an escaped character -- for this test to pass it
3743 // will need to be unescaped by HttpNetworkTransaction.
3744 EXPECT_EQ("b%40r", request.url.password());
3745
[email protected]f9ee6b52008-11-08 06:46:233746 MockWrite data_writes1[] = {
3747 MockWrite("GET / HTTP/1.1\r\n"
3748 "Host: www.google.com\r\n"
3749 "Connection: keep-alive\r\n\r\n"),
3750 };
3751
3752 MockRead data_reads1[] = {
3753 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3754 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3755 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423756 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233757 };
3758
[email protected]31a2bfe2010-02-09 08:03:393759 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3760 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593761 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233762
[email protected]49639fa2011-12-20 23:22:413763 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:413764 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423765 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233766 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423767 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223768 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3769
[email protected]ea9dc9a2009-09-05 00:43:323770 // Empty the current queue.
3771 MessageLoop::current()->RunAllPending();
3772}
3773
[email protected]f9ee6b52008-11-08 06:46:233774// Test that previously tried username/passwords for a realm get re-used.
3775TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593776 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273777 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233778
3779 // Transaction 1: authenticate (foo, bar) on MyRealm1
3780 {
[email protected]1c773ea12009-04-28 19:58:423781 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233782 request.method = "GET";
3783 request.url = GURL("http://www.google.com/x/y/z");
3784 request.load_flags = 0;
3785
[email protected]cb9bf6ca2011-01-28 13:15:273786 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3787
[email protected]f9ee6b52008-11-08 06:46:233788 MockWrite data_writes1[] = {
3789 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3790 "Host: www.google.com\r\n"
3791 "Connection: keep-alive\r\n\r\n"),
3792 };
3793
3794 MockRead data_reads1[] = {
3795 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3796 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3797 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423798 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233799 };
3800
3801 // Resend with authorization (username=foo, password=bar)
3802 MockWrite data_writes2[] = {
3803 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3804 "Host: www.google.com\r\n"
3805 "Connection: keep-alive\r\n"
3806 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3807 };
3808
3809 // Sever accepts the authorization.
3810 MockRead data_reads2[] = {
3811 MockRead("HTTP/1.0 200 OK\r\n"),
3812 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423813 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233814 };
3815
[email protected]31a2bfe2010-02-09 08:03:393816 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3817 data_writes1, arraysize(data_writes1));
3818 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3819 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593820 session_deps.socket_factory.AddSocketDataProvider(&data1);
3821 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233822
[email protected]49639fa2011-12-20 23:22:413823 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233824
[email protected]49639fa2011-12-20 23:22:413825 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423826 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233827
3828 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423829 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233830
[email protected]1c773ea12009-04-28 19:58:423831 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503832 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043833 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:233834
[email protected]49639fa2011-12-20 23:22:413835 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233836
[email protected]49639fa2011-12-20 23:22:413837 rv = trans->RestartWithAuth(
3838 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423839 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233840
3841 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423842 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233843
3844 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503845 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233846 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3847 EXPECT_EQ(100, response->headers->GetContentLength());
3848 }
3849
3850 // ------------------------------------------------------------------------
3851
3852 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3853 {
[email protected]1c773ea12009-04-28 19:58:423854 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233855 request.method = "GET";
3856 // Note that Transaction 1 was at /x/y/z, so this is in the same
3857 // protection space as MyRealm1.
3858 request.url = GURL("http://www.google.com/x/y/a/b");
3859 request.load_flags = 0;
3860
[email protected]cb9bf6ca2011-01-28 13:15:273861 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3862
[email protected]f9ee6b52008-11-08 06:46:233863 MockWrite data_writes1[] = {
3864 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3865 "Host: www.google.com\r\n"
3866 "Connection: keep-alive\r\n"
3867 // Send preemptive authorization for MyRealm1
3868 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3869 };
3870
3871 // The server didn't like the preemptive authorization, and
3872 // challenges us for a different realm (MyRealm2).
3873 MockRead data_reads1[] = {
3874 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3875 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3876 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423877 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233878 };
3879
3880 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3881 MockWrite data_writes2[] = {
3882 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3883 "Host: www.google.com\r\n"
3884 "Connection: keep-alive\r\n"
3885 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3886 };
3887
3888 // Sever accepts the authorization.
3889 MockRead data_reads2[] = {
3890 MockRead("HTTP/1.0 200 OK\r\n"),
3891 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423892 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233893 };
3894
[email protected]31a2bfe2010-02-09 08:03:393895 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3896 data_writes1, arraysize(data_writes1));
3897 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3898 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593899 session_deps.socket_factory.AddSocketDataProvider(&data1);
3900 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233901
[email protected]49639fa2011-12-20 23:22:413902 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233903
[email protected]49639fa2011-12-20 23:22:413904 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423905 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233906
3907 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423908 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233909
[email protected]1c773ea12009-04-28 19:58:423910 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503911 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043912 ASSERT_TRUE(response->auth_challenge.get());
3913 EXPECT_FALSE(response->auth_challenge->is_proxy);
3914 EXPECT_EQ("www.google.com:80",
3915 response->auth_challenge->challenger.ToString());
3916 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
3917 EXPECT_EQ("basic", response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:233918
[email protected]49639fa2011-12-20 23:22:413919 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233920
[email protected]49639fa2011-12-20 23:22:413921 rv = trans->RestartWithAuth(
3922 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423923 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233924
3925 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423926 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233927
3928 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503929 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233930 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3931 EXPECT_EQ(100, response->headers->GetContentLength());
3932 }
3933
3934 // ------------------------------------------------------------------------
3935
3936 // Transaction 3: Resend a request in MyRealm's protection space --
3937 // succeed with preemptive authorization.
3938 {
[email protected]1c773ea12009-04-28 19:58:423939 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233940 request.method = "GET";
3941 request.url = GURL("http://www.google.com/x/y/z2");
3942 request.load_flags = 0;
3943
[email protected]cb9bf6ca2011-01-28 13:15:273944 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3945
[email protected]f9ee6b52008-11-08 06:46:233946 MockWrite data_writes1[] = {
3947 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3948 "Host: www.google.com\r\n"
3949 "Connection: keep-alive\r\n"
3950 // The authorization for MyRealm1 gets sent preemptively
3951 // (since the url is in the same protection space)
3952 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3953 };
3954
3955 // Sever accepts the preemptive authorization
3956 MockRead data_reads1[] = {
3957 MockRead("HTTP/1.0 200 OK\r\n"),
3958 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423959 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233960 };
3961
[email protected]31a2bfe2010-02-09 08:03:393962 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3963 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593964 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233965
[email protected]49639fa2011-12-20 23:22:413966 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233967
[email protected]49639fa2011-12-20 23:22:413968 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423969 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233970
3971 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423972 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233973
[email protected]1c773ea12009-04-28 19:58:423974 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503975 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233976
3977 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3978 EXPECT_EQ(100, response->headers->GetContentLength());
3979 }
3980
3981 // ------------------------------------------------------------------------
3982
3983 // Transaction 4: request another URL in MyRealm (however the
3984 // url is not known to belong to the protection space, so no pre-auth).
3985 {
[email protected]1c773ea12009-04-28 19:58:423986 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233987 request.method = "GET";
3988 request.url = GURL("http://www.google.com/x/1");
3989 request.load_flags = 0;
3990
[email protected]cb9bf6ca2011-01-28 13:15:273991 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3992
[email protected]f9ee6b52008-11-08 06:46:233993 MockWrite data_writes1[] = {
3994 MockWrite("GET /x/1 HTTP/1.1\r\n"
3995 "Host: www.google.com\r\n"
3996 "Connection: keep-alive\r\n\r\n"),
3997 };
3998
3999 MockRead data_reads1[] = {
4000 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4001 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4002 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424003 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234004 };
4005
4006 // Resend with authorization from MyRealm's cache.
4007 MockWrite data_writes2[] = {
4008 MockWrite("GET /x/1 HTTP/1.1\r\n"
4009 "Host: www.google.com\r\n"
4010 "Connection: keep-alive\r\n"
4011 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4012 };
4013
4014 // Sever accepts the authorization.
4015 MockRead data_reads2[] = {
4016 MockRead("HTTP/1.0 200 OK\r\n"),
4017 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424018 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234019 };
4020
[email protected]31a2bfe2010-02-09 08:03:394021 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4022 data_writes1, arraysize(data_writes1));
4023 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4024 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594025 session_deps.socket_factory.AddSocketDataProvider(&data1);
4026 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234027
[email protected]49639fa2011-12-20 23:22:414028 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234029
[email protected]49639fa2011-12-20 23:22:414030 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424031 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234032
4033 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424034 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234035
[email protected]0757e7702009-03-27 04:00:224036 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414037 TestCompletionCallback callback2;
4038 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424039 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224040 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424041 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224042 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4043
[email protected]1c773ea12009-04-28 19:58:424044 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504045 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234046 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4047 EXPECT_EQ(100, response->headers->GetContentLength());
4048 }
4049
4050 // ------------------------------------------------------------------------
4051
4052 // Transaction 5: request a URL in MyRealm, but the server rejects the
4053 // cached identity. Should invalidate and re-prompt.
4054 {
[email protected]1c773ea12009-04-28 19:58:424055 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234056 request.method = "GET";
4057 request.url = GURL("http://www.google.com/p/q/t");
4058 request.load_flags = 0;
4059
[email protected]cb9bf6ca2011-01-28 13:15:274060 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4061
[email protected]f9ee6b52008-11-08 06:46:234062 MockWrite data_writes1[] = {
4063 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4064 "Host: www.google.com\r\n"
4065 "Connection: keep-alive\r\n\r\n"),
4066 };
4067
4068 MockRead data_reads1[] = {
4069 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4070 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4071 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424072 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234073 };
4074
4075 // Resend with authorization from cache for MyRealm.
4076 MockWrite data_writes2[] = {
4077 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4078 "Host: www.google.com\r\n"
4079 "Connection: keep-alive\r\n"
4080 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4081 };
4082
4083 // Sever rejects the authorization.
4084 MockRead data_reads2[] = {
4085 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4086 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4087 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424088 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234089 };
4090
4091 // At this point we should prompt for new credentials for MyRealm.
4092 // Restart with username=foo3, password=foo4.
4093 MockWrite data_writes3[] = {
4094 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4095 "Host: www.google.com\r\n"
4096 "Connection: keep-alive\r\n"
4097 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4098 };
4099
4100 // Sever accepts the authorization.
4101 MockRead data_reads3[] = {
4102 MockRead("HTTP/1.0 200 OK\r\n"),
4103 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424104 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234105 };
4106
[email protected]31a2bfe2010-02-09 08:03:394107 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4108 data_writes1, arraysize(data_writes1));
4109 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4110 data_writes2, arraysize(data_writes2));
4111 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4112 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594113 session_deps.socket_factory.AddSocketDataProvider(&data1);
4114 session_deps.socket_factory.AddSocketDataProvider(&data2);
4115 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234116
[email protected]49639fa2011-12-20 23:22:414117 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234118
[email protected]49639fa2011-12-20 23:22:414119 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424120 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234121
4122 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424123 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234124
[email protected]0757e7702009-03-27 04:00:224125 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414126 TestCompletionCallback callback2;
4127 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424128 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224129 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424130 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224131 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4132
[email protected]1c773ea12009-04-28 19:58:424133 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504134 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044135 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:234136
[email protected]49639fa2011-12-20 23:22:414137 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234138
[email protected]49639fa2011-12-20 23:22:414139 rv = trans->RestartWithAuth(
4140 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:424141 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234142
[email protected]0757e7702009-03-27 04:00:224143 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424144 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234145
4146 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504147 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234148 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4149 EXPECT_EQ(100, response->headers->GetContentLength());
4150 }
4151}
[email protected]89ceba9a2009-03-21 03:46:064152
[email protected]3c32c5f2010-05-18 15:18:124153// Tests that nonce count increments when multiple auth attempts
4154// are started with the same nonce.
4155TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4156 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444157 HttpAuthHandlerDigest::Factory* digest_factory =
4158 new HttpAuthHandlerDigest::Factory();
4159 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4160 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4161 digest_factory->set_nonce_generator(nonce_generator);
4162 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274163 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124164
4165 // Transaction 1: authenticate (foo, bar) on MyRealm1
4166 {
[email protected]3c32c5f2010-05-18 15:18:124167 HttpRequestInfo request;
4168 request.method = "GET";
4169 request.url = GURL("http://www.google.com/x/y/z");
4170 request.load_flags = 0;
4171
[email protected]cb9bf6ca2011-01-28 13:15:274172 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4173
[email protected]3c32c5f2010-05-18 15:18:124174 MockWrite data_writes1[] = {
4175 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4176 "Host: www.google.com\r\n"
4177 "Connection: keep-alive\r\n\r\n"),
4178 };
4179
4180 MockRead data_reads1[] = {
4181 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4182 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4183 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4184 MockRead(false, OK),
4185 };
4186
4187 // Resend with authorization (username=foo, password=bar)
4188 MockWrite data_writes2[] = {
4189 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4190 "Host: www.google.com\r\n"
4191 "Connection: keep-alive\r\n"
4192 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4193 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4194 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4195 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4196 };
4197
4198 // Sever accepts the authorization.
4199 MockRead data_reads2[] = {
4200 MockRead("HTTP/1.0 200 OK\r\n"),
4201 MockRead(false, OK),
4202 };
4203
4204 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4205 data_writes1, arraysize(data_writes1));
4206 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4207 data_writes2, arraysize(data_writes2));
4208 session_deps.socket_factory.AddSocketDataProvider(&data1);
4209 session_deps.socket_factory.AddSocketDataProvider(&data2);
4210
[email protected]49639fa2011-12-20 23:22:414211 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124212
[email protected]49639fa2011-12-20 23:22:414213 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124214 EXPECT_EQ(ERR_IO_PENDING, rv);
4215
4216 rv = callback1.WaitForResult();
4217 EXPECT_EQ(OK, rv);
4218
4219 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504220 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044221 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:124222
[email protected]49639fa2011-12-20 23:22:414223 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:124224
[email protected]49639fa2011-12-20 23:22:414225 rv = trans->RestartWithAuth(
4226 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:124227 EXPECT_EQ(ERR_IO_PENDING, rv);
4228
4229 rv = callback2.WaitForResult();
4230 EXPECT_EQ(OK, rv);
4231
4232 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504233 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124234 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4235 }
4236
4237 // ------------------------------------------------------------------------
4238
4239 // Transaction 2: Request another resource in digestive's protection space.
4240 // This will preemptively add an Authorization header which should have an
4241 // "nc" value of 2 (as compared to 1 in the first use.
4242 {
[email protected]3c32c5f2010-05-18 15:18:124243 HttpRequestInfo request;
4244 request.method = "GET";
4245 // Note that Transaction 1 was at /x/y/z, so this is in the same
4246 // protection space as digest.
4247 request.url = GURL("http://www.google.com/x/y/a/b");
4248 request.load_flags = 0;
4249
[email protected]cb9bf6ca2011-01-28 13:15:274250 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4251
[email protected]3c32c5f2010-05-18 15:18:124252 MockWrite data_writes1[] = {
4253 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4254 "Host: www.google.com\r\n"
4255 "Connection: keep-alive\r\n"
4256 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4257 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4258 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4259 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4260 };
4261
4262 // Sever accepts the authorization.
4263 MockRead data_reads1[] = {
4264 MockRead("HTTP/1.0 200 OK\r\n"),
4265 MockRead("Content-Length: 100\r\n\r\n"),
4266 MockRead(false, OK),
4267 };
4268
4269 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4270 data_writes1, arraysize(data_writes1));
4271 session_deps.socket_factory.AddSocketDataProvider(&data1);
4272
[email protected]49639fa2011-12-20 23:22:414273 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124274
[email protected]49639fa2011-12-20 23:22:414275 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124276 EXPECT_EQ(ERR_IO_PENDING, rv);
4277
4278 rv = callback1.WaitForResult();
4279 EXPECT_EQ(OK, rv);
4280
4281 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504282 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124283 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4284 }
4285}
4286
[email protected]89ceba9a2009-03-21 03:46:064287// Test the ResetStateForRestart() private method.
4288TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4289 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594290 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404291 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434292 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064293
4294 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064295 trans->read_buf_ = new IOBuffer(15);
4296 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204297 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064298
4299 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144300 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574301 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:084302 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:574303 response->response_time = base::Time::Now();
4304 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064305
4306 { // Setup state for response_.vary_data
4307 HttpRequestInfo request;
4308 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4309 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274310 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434311 request.extra_headers.SetHeader("Foo", "1");
4312 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574313 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064314 }
4315
4316 // Cause the above state to be reset.
4317 trans->ResetStateForRestart();
4318
4319 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074320 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064321 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204322 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574323 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4324 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044325 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:084326 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:574327 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064328}
4329
[email protected]bacff652009-03-31 17:50:334330// Test HTTPS connections to a site with a bad certificate
4331TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334332 HttpRequestInfo request;
4333 request.method = "GET";
4334 request.url = GURL("https://www.google.com/");
4335 request.load_flags = 0;
4336
[email protected]cb9bf6ca2011-01-28 13:15:274337 SessionDependencies session_deps;
4338 scoped_ptr<HttpTransaction> trans(
4339 new HttpNetworkTransaction(CreateSession(&session_deps)));
4340
[email protected]bacff652009-03-31 17:50:334341 MockWrite data_writes[] = {
4342 MockWrite("GET / HTTP/1.1\r\n"
4343 "Host: www.google.com\r\n"
4344 "Connection: keep-alive\r\n\r\n"),
4345 };
4346
4347 MockRead data_reads[] = {
4348 MockRead("HTTP/1.0 200 OK\r\n"),
4349 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4350 MockRead("Content-Length: 100\r\n\r\n"),
4351 MockRead(false, OK),
4352 };
4353
[email protected]5ecc992a42009-11-11 01:41:594354 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394355 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4356 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594357 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4358 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334359
[email protected]5ecc992a42009-11-11 01:41:594360 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4361 session_deps.socket_factory.AddSocketDataProvider(&data);
4362 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4363 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334364
[email protected]49639fa2011-12-20 23:22:414365 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334366
[email protected]49639fa2011-12-20 23:22:414367 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334368 EXPECT_EQ(ERR_IO_PENDING, rv);
4369
4370 rv = callback.WaitForResult();
4371 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4372
[email protected]49639fa2011-12-20 23:22:414373 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334374 EXPECT_EQ(ERR_IO_PENDING, rv);
4375
4376 rv = callback.WaitForResult();
4377 EXPECT_EQ(OK, rv);
4378
4379 const HttpResponseInfo* response = trans->GetResponseInfo();
4380
[email protected]fe2255a2011-09-20 19:37:504381 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334382 EXPECT_EQ(100, response->headers->GetContentLength());
4383}
4384
4385// Test HTTPS connections to a site with a bad certificate, going through a
4386// proxy
4387TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004388 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334389
4390 HttpRequestInfo request;
4391 request.method = "GET";
4392 request.url = GURL("https://www.google.com/");
4393 request.load_flags = 0;
4394
4395 MockWrite proxy_writes[] = {
4396 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454397 "Host: www.google.com\r\n"
4398 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334399 };
4400
4401 MockRead proxy_reads[] = {
4402 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424403 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334404 };
4405
4406 MockWrite data_writes[] = {
4407 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454408 "Host: www.google.com\r\n"
4409 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334410 MockWrite("GET / HTTP/1.1\r\n"
4411 "Host: www.google.com\r\n"
4412 "Connection: keep-alive\r\n\r\n"),
4413 };
4414
4415 MockRead data_reads[] = {
4416 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4417 MockRead("HTTP/1.0 200 OK\r\n"),
4418 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4419 MockRead("Content-Length: 100\r\n\r\n"),
4420 MockRead(false, OK),
4421 };
4422
[email protected]31a2bfe2010-02-09 08:03:394423 StaticSocketDataProvider ssl_bad_certificate(
4424 proxy_reads, arraysize(proxy_reads),
4425 proxy_writes, arraysize(proxy_writes));
4426 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4427 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594428 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4429 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334430
[email protected]5ecc992a42009-11-11 01:41:594431 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4432 session_deps.socket_factory.AddSocketDataProvider(&data);
4433 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334435
[email protected]49639fa2011-12-20 23:22:414436 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334437
4438 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594439 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334440
[email protected]d207a5f2009-06-04 05:28:404441 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434442 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334443
[email protected]49639fa2011-12-20 23:22:414444 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334445 EXPECT_EQ(ERR_IO_PENDING, rv);
4446
4447 rv = callback.WaitForResult();
4448 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4449
[email protected]49639fa2011-12-20 23:22:414450 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334451 EXPECT_EQ(ERR_IO_PENDING, rv);
4452
4453 rv = callback.WaitForResult();
4454 EXPECT_EQ(OK, rv);
4455
4456 const HttpResponseInfo* response = trans->GetResponseInfo();
4457
[email protected]fe2255a2011-09-20 19:37:504458 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334459 EXPECT_EQ(100, response->headers->GetContentLength());
4460 }
4461}
4462
[email protected]2df19bb2010-08-25 20:13:464463
4464// Test HTTPS connections to a site, going through an HTTPS proxy
4465TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114466 SessionDependencies session_deps(ProxyService::CreateFixed(
4467 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464468
4469 HttpRequestInfo request;
4470 request.method = "GET";
4471 request.url = GURL("https://www.google.com/");
4472 request.load_flags = 0;
4473
4474 MockWrite data_writes[] = {
4475 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4476 "Host: www.google.com\r\n"
4477 "Proxy-Connection: keep-alive\r\n\r\n"),
4478 MockWrite("GET / HTTP/1.1\r\n"
4479 "Host: www.google.com\r\n"
4480 "Connection: keep-alive\r\n\r\n"),
4481 };
4482
4483 MockRead data_reads[] = {
4484 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4485 MockRead("HTTP/1.1 200 OK\r\n"),
4486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4487 MockRead("Content-Length: 100\r\n\r\n"),
4488 MockRead(false, OK),
4489 };
4490
4491 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4492 data_writes, arraysize(data_writes));
4493 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4494 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4495
4496 session_deps.socket_factory.AddSocketDataProvider(&data);
4497 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4498 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4499
[email protected]49639fa2011-12-20 23:22:414500 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464501
4502 scoped_ptr<HttpTransaction> trans(
4503 new HttpNetworkTransaction(CreateSession(&session_deps)));
4504
[email protected]49639fa2011-12-20 23:22:414505 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464506 EXPECT_EQ(ERR_IO_PENDING, rv);
4507
4508 rv = callback.WaitForResult();
4509 EXPECT_EQ(OK, rv);
4510 const HttpResponseInfo* response = trans->GetResponseInfo();
4511
[email protected]fe2255a2011-09-20 19:37:504512 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464513
4514 EXPECT_TRUE(response->headers->IsKeepAlive());
4515 EXPECT_EQ(200, response->headers->response_code());
4516 EXPECT_EQ(100, response->headers->GetContentLength());
4517 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4518}
4519
[email protected]511f6f52010-12-17 03:58:294520// Test an HTTPS Proxy's ability to redirect a CONNECT request
4521TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4522 SessionDependencies session_deps(
4523 ProxyService::CreateFixed("https://proxy:70"));
4524
4525 HttpRequestInfo request;
4526 request.method = "GET";
4527 request.url = GURL("https://www.google.com/");
4528 request.load_flags = 0;
4529
4530 MockWrite data_writes[] = {
4531 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4532 "Host: www.google.com\r\n"
4533 "Proxy-Connection: keep-alive\r\n\r\n"),
4534 };
4535
4536 MockRead data_reads[] = {
4537 MockRead("HTTP/1.1 302 Redirect\r\n"),
4538 MockRead("Location: http://login.example.com/\r\n"),
4539 MockRead("Content-Length: 0\r\n\r\n"),
4540 MockRead(false, OK),
4541 };
4542
4543 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4544 data_writes, arraysize(data_writes));
4545 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4546
4547 session_deps.socket_factory.AddSocketDataProvider(&data);
4548 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4549
[email protected]49639fa2011-12-20 23:22:414550 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294551
4552 scoped_ptr<HttpTransaction> trans(
4553 new HttpNetworkTransaction(CreateSession(&session_deps)));
4554
[email protected]49639fa2011-12-20 23:22:414555 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294556 EXPECT_EQ(ERR_IO_PENDING, rv);
4557
4558 rv = callback.WaitForResult();
4559 EXPECT_EQ(OK, rv);
4560 const HttpResponseInfo* response = trans->GetResponseInfo();
4561
[email protected]fe2255a2011-09-20 19:37:504562 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294563
4564 EXPECT_EQ(302, response->headers->response_code());
4565 std::string url;
4566 EXPECT_TRUE(response->headers->IsRedirect(&url));
4567 EXPECT_EQ("http://login.example.com/", url);
4568}
4569
4570// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4571TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4572 SessionDependencies session_deps(
4573 ProxyService::CreateFixed("https://proxy:70"));
4574
4575 HttpRequestInfo request;
4576 request.method = "GET";
4577 request.url = GURL("https://www.google.com/");
4578 request.load_flags = 0;
4579
4580 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4581 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4582 MockWrite data_writes[] = {
4583 CreateMockWrite(*conn.get(), 0, false),
4584 };
4585
4586 static const char* const kExtraHeaders[] = {
4587 "location",
4588 "http://login.example.com/",
4589 };
4590 scoped_ptr<spdy::SpdyFrame> resp(
4591 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4592 arraysize(kExtraHeaders)/2, 1));
4593 MockRead data_reads[] = {
4594 CreateMockRead(*resp.get(), 1, false),
4595 MockRead(true, 0, 2), // EOF
4596 };
4597
[email protected]a1595312012-01-22 03:25:044598 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294599 new DelayedSocketData(
4600 1, // wait for one write to finish before reading.
4601 data_reads, arraysize(data_reads),
4602 data_writes, arraysize(data_writes)));
4603 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4604 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:204605 proxy_ssl.next_proto = "spdy/2.1";
[email protected]511f6f52010-12-17 03:58:294606 proxy_ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:204607 proxy_ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]511f6f52010-12-17 03:58:294608
4609 session_deps.socket_factory.AddSocketDataProvider(data.get());
4610 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4611
[email protected]49639fa2011-12-20 23:22:414612 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294613
4614 scoped_ptr<HttpTransaction> trans(
4615 new HttpNetworkTransaction(CreateSession(&session_deps)));
4616
[email protected]49639fa2011-12-20 23:22:414617 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294618 EXPECT_EQ(ERR_IO_PENDING, rv);
4619
4620 rv = callback.WaitForResult();
4621 EXPECT_EQ(OK, rv);
4622 const HttpResponseInfo* response = trans->GetResponseInfo();
4623
[email protected]fe2255a2011-09-20 19:37:504624 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294625
4626 EXPECT_EQ(302, response->headers->response_code());
4627 std::string url;
4628 EXPECT_TRUE(response->headers->IsRedirect(&url));
4629 EXPECT_EQ("http://login.example.com/", url);
4630}
4631
4632// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4633TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4634 SessionDependencies session_deps(
4635 ProxyService::CreateFixed("https://proxy:70"));
4636
4637 HttpRequestInfo request;
4638 request.method = "GET";
4639 request.url = GURL("https://www.google.com/");
4640 request.load_flags = 0;
4641
4642 MockWrite data_writes[] = {
4643 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4644 "Host: www.google.com\r\n"
4645 "Proxy-Connection: keep-alive\r\n\r\n"),
4646 };
4647
4648 MockRead data_reads[] = {
4649 MockRead("HTTP/1.1 404 Not Found\r\n"),
4650 MockRead("Content-Length: 23\r\n\r\n"),
4651 MockRead("The host does not exist"),
4652 MockRead(false, OK),
4653 };
4654
4655 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4656 data_writes, arraysize(data_writes));
4657 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4658
4659 session_deps.socket_factory.AddSocketDataProvider(&data);
4660 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4661
[email protected]49639fa2011-12-20 23:22:414662 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294663
4664 scoped_ptr<HttpTransaction> trans(
4665 new HttpNetworkTransaction(CreateSession(&session_deps)));
4666
[email protected]49639fa2011-12-20 23:22:414667 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294668 EXPECT_EQ(ERR_IO_PENDING, rv);
4669
4670 rv = callback.WaitForResult();
4671 EXPECT_EQ(OK, rv);
4672 const HttpResponseInfo* response = trans->GetResponseInfo();
4673
[email protected]fe2255a2011-09-20 19:37:504674 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294675
4676 EXPECT_EQ(404, response->headers->response_code());
4677 EXPECT_EQ(23, response->headers->GetContentLength());
4678 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4679 EXPECT_FALSE(response->ssl_info.is_valid());
4680
4681 std::string response_data;
4682 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4683 EXPECT_EQ("The host does not exist", response_data);
4684}
4685
4686// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4687// request
4688TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4689 SessionDependencies session_deps(
4690 ProxyService::CreateFixed("https://proxy:70"));
4691
4692 HttpRequestInfo request;
4693 request.method = "GET";
4694 request.url = GURL("https://www.google.com/");
4695 request.load_flags = 0;
4696
4697 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4698 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4699 MockWrite data_writes[] = {
4700 CreateMockWrite(*conn.get(), 0, false),
4701 };
4702
4703 static const char* const kExtraHeaders[] = {
4704 "location",
4705 "http://login.example.com/",
4706 };
4707 scoped_ptr<spdy::SpdyFrame> resp(
4708 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4709 arraysize(kExtraHeaders)/2, 1));
4710 scoped_ptr<spdy::SpdyFrame> body(
4711 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4712 MockRead data_reads[] = {
4713 CreateMockRead(*resp.get(), 1, false),
4714 CreateMockRead(*body.get(), 2, false),
4715 MockRead(true, 0, 3), // EOF
4716 };
4717
[email protected]a1595312012-01-22 03:25:044718 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294719 new DelayedSocketData(
4720 1, // wait for one write to finish before reading.
4721 data_reads, arraysize(data_reads),
4722 data_writes, arraysize(data_writes)));
4723 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4724 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:204725 proxy_ssl.next_proto = "spdy/2.1";
[email protected]511f6f52010-12-17 03:58:294726 proxy_ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:204727 proxy_ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]511f6f52010-12-17 03:58:294728
4729 session_deps.socket_factory.AddSocketDataProvider(data.get());
4730 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4731
[email protected]49639fa2011-12-20 23:22:414732 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294733
4734 scoped_ptr<HttpTransaction> trans(
4735 new HttpNetworkTransaction(CreateSession(&session_deps)));
4736
[email protected]49639fa2011-12-20 23:22:414737 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294738 EXPECT_EQ(ERR_IO_PENDING, rv);
4739
4740 rv = callback.WaitForResult();
4741 EXPECT_EQ(OK, rv);
4742 const HttpResponseInfo* response = trans->GetResponseInfo();
4743
[email protected]fe2255a2011-09-20 19:37:504744 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294745
4746 EXPECT_EQ(404, response->headers->response_code());
4747 EXPECT_FALSE(response->ssl_info.is_valid());
4748
4749 std::string response_data;
4750 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4751 EXPECT_EQ("The host does not exist", response_data);
4752}
4753
[email protected]2df19bb2010-08-25 20:13:464754// Test HTTPS connections to a site with a bad certificate, going through an
4755// HTTPS proxy
4756TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114757 SessionDependencies session_deps(ProxyService::CreateFixed(
4758 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464759
4760 HttpRequestInfo request;
4761 request.method = "GET";
4762 request.url = GURL("https://www.google.com/");
4763 request.load_flags = 0;
4764
4765 // Attempt to fetch the URL from a server with a bad cert
4766 MockWrite bad_cert_writes[] = {
4767 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4768 "Host: www.google.com\r\n"
4769 "Proxy-Connection: keep-alive\r\n\r\n"),
4770 };
4771
4772 MockRead bad_cert_reads[] = {
4773 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4774 MockRead(false, OK)
4775 };
4776
4777 // Attempt to fetch the URL with a good cert
4778 MockWrite good_data_writes[] = {
4779 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4780 "Host: www.google.com\r\n"
4781 "Proxy-Connection: keep-alive\r\n\r\n"),
4782 MockWrite("GET / HTTP/1.1\r\n"
4783 "Host: www.google.com\r\n"
4784 "Connection: keep-alive\r\n\r\n"),
4785 };
4786
4787 MockRead good_cert_reads[] = {
4788 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4789 MockRead("HTTP/1.0 200 OK\r\n"),
4790 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4791 MockRead("Content-Length: 100\r\n\r\n"),
4792 MockRead(false, OK),
4793 };
4794
4795 StaticSocketDataProvider ssl_bad_certificate(
4796 bad_cert_reads, arraysize(bad_cert_reads),
4797 bad_cert_writes, arraysize(bad_cert_writes));
4798 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4799 good_data_writes, arraysize(good_data_writes));
4800 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4801 SSLSocketDataProvider ssl(true, OK);
4802
4803 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4804 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4805 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4806 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4807
4808 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4809 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4810 session_deps.socket_factory.AddSocketDataProvider(&data);
4811 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4812
[email protected]49639fa2011-12-20 23:22:414813 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464814
4815 scoped_ptr<HttpTransaction> trans(
4816 new HttpNetworkTransaction(CreateSession(&session_deps)));
4817
[email protected]49639fa2011-12-20 23:22:414818 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464819 EXPECT_EQ(ERR_IO_PENDING, rv);
4820
4821 rv = callback.WaitForResult();
4822 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4823
[email protected]49639fa2011-12-20 23:22:414824 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:464825 EXPECT_EQ(ERR_IO_PENDING, rv);
4826
4827 rv = callback.WaitForResult();
4828 EXPECT_EQ(OK, rv);
4829
4830 const HttpResponseInfo* response = trans->GetResponseInfo();
4831
[email protected]fe2255a2011-09-20 19:37:504832 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464833 EXPECT_EQ(100, response->headers->GetContentLength());
4834}
4835
[email protected]1c773ea12009-04-28 19:58:424836TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424837 HttpRequestInfo request;
4838 request.method = "GET";
4839 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434840 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4841 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424842
[email protected]cb9bf6ca2011-01-28 13:15:274843 SessionDependencies session_deps;
4844 scoped_ptr<HttpTransaction> trans(
4845 new HttpNetworkTransaction(CreateSession(&session_deps)));
4846
[email protected]1c773ea12009-04-28 19:58:424847 MockWrite data_writes[] = {
4848 MockWrite("GET / HTTP/1.1\r\n"
4849 "Host: www.google.com\r\n"
4850 "Connection: keep-alive\r\n"
4851 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4852 };
4853
4854 // Lastly, the server responds with the actual content.
4855 MockRead data_reads[] = {
4856 MockRead("HTTP/1.0 200 OK\r\n"),
4857 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4858 MockRead("Content-Length: 100\r\n\r\n"),
4859 MockRead(false, OK),
4860 };
4861
[email protected]31a2bfe2010-02-09 08:03:394862 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4863 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594864 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424865
[email protected]49639fa2011-12-20 23:22:414866 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424867
[email protected]49639fa2011-12-20 23:22:414868 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424869 EXPECT_EQ(ERR_IO_PENDING, rv);
4870
4871 rv = callback.WaitForResult();
4872 EXPECT_EQ(OK, rv);
4873}
4874
[email protected]da81f132010-08-18 23:39:294875TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294876 HttpRequestInfo request;
4877 request.method = "GET";
4878 request.url = GURL("https://www.google.com/");
4879 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4880 "Chromium Ultra Awesome X Edition");
4881
[email protected]cb9bf6ca2011-01-28 13:15:274882 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4883 scoped_ptr<HttpTransaction> trans(
4884 new HttpNetworkTransaction(CreateSession(&session_deps)));
4885
[email protected]da81f132010-08-18 23:39:294886 MockWrite data_writes[] = {
4887 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4888 "Host: www.google.com\r\n"
4889 "Proxy-Connection: keep-alive\r\n"
4890 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4891 };
4892 MockRead data_reads[] = {
4893 // Return an error, so the transaction stops here (this test isn't
4894 // interested in the rest).
4895 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4896 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4897 MockRead("Proxy-Connection: close\r\n\r\n"),
4898 };
4899
4900 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4901 data_writes, arraysize(data_writes));
4902 session_deps.socket_factory.AddSocketDataProvider(&data);
4903
[email protected]49639fa2011-12-20 23:22:414904 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:294905
[email protected]49639fa2011-12-20 23:22:414906 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:294907 EXPECT_EQ(ERR_IO_PENDING, rv);
4908
4909 rv = callback.WaitForResult();
4910 EXPECT_EQ(OK, rv);
4911}
4912
[email protected]1c773ea12009-04-28 19:58:424913TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424914 HttpRequestInfo request;
4915 request.method = "GET";
4916 request.url = GURL("http://www.google.com/");
4917 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:164918 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
4919 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:424920
[email protected]cb9bf6ca2011-01-28 13:15:274921 SessionDependencies session_deps;
4922 scoped_ptr<HttpTransaction> trans(
4923 new HttpNetworkTransaction(CreateSession(&session_deps)));
4924
[email protected]1c773ea12009-04-28 19:58:424925 MockWrite data_writes[] = {
4926 MockWrite("GET / HTTP/1.1\r\n"
4927 "Host: www.google.com\r\n"
4928 "Connection: keep-alive\r\n"
4929 "Referer: http://the.previous.site.com/\r\n\r\n"),
4930 };
4931
4932 // Lastly, the server responds with the actual content.
4933 MockRead data_reads[] = {
4934 MockRead("HTTP/1.0 200 OK\r\n"),
4935 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4936 MockRead("Content-Length: 100\r\n\r\n"),
4937 MockRead(false, OK),
4938 };
4939
[email protected]31a2bfe2010-02-09 08:03:394940 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4941 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594942 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424943
[email protected]49639fa2011-12-20 23:22:414944 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424945
[email protected]49639fa2011-12-20 23:22:414946 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424947 EXPECT_EQ(ERR_IO_PENDING, rv);
4948
4949 rv = callback.WaitForResult();
4950 EXPECT_EQ(OK, rv);
4951}
4952
4953TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424954 HttpRequestInfo request;
4955 request.method = "POST";
4956 request.url = GURL("http://www.google.com/");
4957
[email protected]cb9bf6ca2011-01-28 13:15:274958 SessionDependencies session_deps;
4959 scoped_ptr<HttpTransaction> trans(
4960 new HttpNetworkTransaction(CreateSession(&session_deps)));
4961
[email protected]1c773ea12009-04-28 19:58:424962 MockWrite data_writes[] = {
4963 MockWrite("POST / HTTP/1.1\r\n"
4964 "Host: www.google.com\r\n"
4965 "Connection: keep-alive\r\n"
4966 "Content-Length: 0\r\n\r\n"),
4967 };
4968
4969 // Lastly, the server responds with the actual content.
4970 MockRead data_reads[] = {
4971 MockRead("HTTP/1.0 200 OK\r\n"),
4972 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4973 MockRead("Content-Length: 100\r\n\r\n"),
4974 MockRead(false, OK),
4975 };
4976
[email protected]31a2bfe2010-02-09 08:03:394977 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4978 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594979 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424980
[email protected]49639fa2011-12-20 23:22:414981 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424982
[email protected]49639fa2011-12-20 23:22:414983 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424984 EXPECT_EQ(ERR_IO_PENDING, rv);
4985
4986 rv = callback.WaitForResult();
4987 EXPECT_EQ(OK, rv);
4988}
4989
4990TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424991 HttpRequestInfo request;
4992 request.method = "PUT";
4993 request.url = GURL("http://www.google.com/");
4994
[email protected]cb9bf6ca2011-01-28 13:15:274995 SessionDependencies session_deps;
4996 scoped_ptr<HttpTransaction> trans(
4997 new HttpNetworkTransaction(CreateSession(&session_deps)));
4998
[email protected]1c773ea12009-04-28 19:58:424999 MockWrite data_writes[] = {
5000 MockWrite("PUT / HTTP/1.1\r\n"
5001 "Host: www.google.com\r\n"
5002 "Connection: keep-alive\r\n"
5003 "Content-Length: 0\r\n\r\n"),
5004 };
5005
5006 // Lastly, the server responds with the actual content.
5007 MockRead data_reads[] = {
5008 MockRead("HTTP/1.0 200 OK\r\n"),
5009 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5010 MockRead("Content-Length: 100\r\n\r\n"),
5011 MockRead(false, OK),
5012 };
5013
[email protected]31a2bfe2010-02-09 08:03:395014 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5015 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595016 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425017
[email protected]49639fa2011-12-20 23:22:415018 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425019
[email protected]49639fa2011-12-20 23:22:415020 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425021 EXPECT_EQ(ERR_IO_PENDING, rv);
5022
5023 rv = callback.WaitForResult();
5024 EXPECT_EQ(OK, rv);
5025}
5026
5027TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425028 HttpRequestInfo request;
5029 request.method = "HEAD";
5030 request.url = GURL("http://www.google.com/");
5031
[email protected]cb9bf6ca2011-01-28 13:15:275032 SessionDependencies session_deps;
5033 scoped_ptr<HttpTransaction> trans(
5034 new HttpNetworkTransaction(CreateSession(&session_deps)));
5035
[email protected]1c773ea12009-04-28 19:58:425036 MockWrite data_writes[] = {
5037 MockWrite("HEAD / HTTP/1.1\r\n"
5038 "Host: www.google.com\r\n"
5039 "Connection: keep-alive\r\n"
5040 "Content-Length: 0\r\n\r\n"),
5041 };
5042
5043 // Lastly, the server responds with the actual content.
5044 MockRead data_reads[] = {
5045 MockRead("HTTP/1.0 200 OK\r\n"),
5046 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5047 MockRead("Content-Length: 100\r\n\r\n"),
5048 MockRead(false, OK),
5049 };
5050
[email protected]31a2bfe2010-02-09 08:03:395051 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5052 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595053 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425054
[email protected]49639fa2011-12-20 23:22:415055 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425056
[email protected]49639fa2011-12-20 23:22:415057 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425058 EXPECT_EQ(ERR_IO_PENDING, rv);
5059
5060 rv = callback.WaitForResult();
5061 EXPECT_EQ(OK, rv);
5062}
5063
5064TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425065 HttpRequestInfo request;
5066 request.method = "GET";
5067 request.url = GURL("http://www.google.com/");
5068 request.load_flags = LOAD_BYPASS_CACHE;
5069
[email protected]cb9bf6ca2011-01-28 13:15:275070 SessionDependencies session_deps;
5071 scoped_ptr<HttpTransaction> trans(
5072 new HttpNetworkTransaction(CreateSession(&session_deps)));
5073
[email protected]1c773ea12009-04-28 19:58:425074 MockWrite data_writes[] = {
5075 MockWrite("GET / HTTP/1.1\r\n"
5076 "Host: www.google.com\r\n"
5077 "Connection: keep-alive\r\n"
5078 "Pragma: no-cache\r\n"
5079 "Cache-Control: no-cache\r\n\r\n"),
5080 };
5081
5082 // Lastly, the server responds with the actual content.
5083 MockRead data_reads[] = {
5084 MockRead("HTTP/1.0 200 OK\r\n"),
5085 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5086 MockRead("Content-Length: 100\r\n\r\n"),
5087 MockRead(false, OK),
5088 };
5089
[email protected]31a2bfe2010-02-09 08:03:395090 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5091 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595092 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425093
[email protected]49639fa2011-12-20 23:22:415094 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425095
[email protected]49639fa2011-12-20 23:22:415096 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425097 EXPECT_EQ(ERR_IO_PENDING, rv);
5098
5099 rv = callback.WaitForResult();
5100 EXPECT_EQ(OK, rv);
5101}
5102
5103TEST_F(HttpNetworkTransactionTest,
5104 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425105 HttpRequestInfo request;
5106 request.method = "GET";
5107 request.url = GURL("http://www.google.com/");
5108 request.load_flags = LOAD_VALIDATE_CACHE;
5109
[email protected]cb9bf6ca2011-01-28 13:15:275110 SessionDependencies session_deps;
5111 scoped_ptr<HttpTransaction> trans(
5112 new HttpNetworkTransaction(CreateSession(&session_deps)));
5113
[email protected]1c773ea12009-04-28 19:58:425114 MockWrite data_writes[] = {
5115 MockWrite("GET / HTTP/1.1\r\n"
5116 "Host: www.google.com\r\n"
5117 "Connection: keep-alive\r\n"
5118 "Cache-Control: max-age=0\r\n\r\n"),
5119 };
5120
5121 // Lastly, the server responds with the actual content.
5122 MockRead data_reads[] = {
5123 MockRead("HTTP/1.0 200 OK\r\n"),
5124 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5125 MockRead("Content-Length: 100\r\n\r\n"),
5126 MockRead(false, OK),
5127 };
5128
[email protected]31a2bfe2010-02-09 08:03:395129 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5130 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595131 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425132
[email protected]49639fa2011-12-20 23:22:415133 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425134
[email protected]49639fa2011-12-20 23:22:415135 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425136 EXPECT_EQ(ERR_IO_PENDING, rv);
5137
5138 rv = callback.WaitForResult();
5139 EXPECT_EQ(OK, rv);
5140}
5141
5142TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425143 HttpRequestInfo request;
5144 request.method = "GET";
5145 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435146 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425147
[email protected]cb9bf6ca2011-01-28 13:15:275148 SessionDependencies session_deps;
5149 scoped_ptr<HttpTransaction> trans(
5150 new HttpNetworkTransaction(CreateSession(&session_deps)));
5151
[email protected]1c773ea12009-04-28 19:58:425152 MockWrite data_writes[] = {
5153 MockWrite("GET / HTTP/1.1\r\n"
5154 "Host: www.google.com\r\n"
5155 "Connection: keep-alive\r\n"
5156 "FooHeader: Bar\r\n\r\n"),
5157 };
5158
5159 // Lastly, the server responds with the actual content.
5160 MockRead data_reads[] = {
5161 MockRead("HTTP/1.0 200 OK\r\n"),
5162 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5163 MockRead("Content-Length: 100\r\n\r\n"),
5164 MockRead(false, OK),
5165 };
5166
[email protected]31a2bfe2010-02-09 08:03:395167 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5168 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595169 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425170
[email protected]49639fa2011-12-20 23:22:415171 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425172
[email protected]49639fa2011-12-20 23:22:415173 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425174 EXPECT_EQ(ERR_IO_PENDING, rv);
5175
5176 rv = callback.WaitForResult();
5177 EXPECT_EQ(OK, rv);
5178}
5179
[email protected]270c6412010-03-29 22:02:475180TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475181 HttpRequestInfo request;
5182 request.method = "GET";
5183 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435184 request.extra_headers.SetHeader("referer", "www.foo.com");
5185 request.extra_headers.SetHeader("hEllo", "Kitty");
5186 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475187
[email protected]cb9bf6ca2011-01-28 13:15:275188 SessionDependencies session_deps;
5189 scoped_ptr<HttpTransaction> trans(
5190 new HttpNetworkTransaction(CreateSession(&session_deps)));
5191
[email protected]270c6412010-03-29 22:02:475192 MockWrite data_writes[] = {
5193 MockWrite("GET / HTTP/1.1\r\n"
5194 "Host: www.google.com\r\n"
5195 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165196 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475197 "hEllo: Kitty\r\n"
5198 "FoO: bar\r\n\r\n"),
5199 };
5200
5201 // Lastly, the server responds with the actual content.
5202 MockRead data_reads[] = {
5203 MockRead("HTTP/1.0 200 OK\r\n"),
5204 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5205 MockRead("Content-Length: 100\r\n\r\n"),
5206 MockRead(false, OK),
5207 };
5208
5209 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5210 data_writes, arraysize(data_writes));
5211 session_deps.socket_factory.AddSocketDataProvider(&data);
5212
[email protected]49639fa2011-12-20 23:22:415213 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:475214
[email protected]49639fa2011-12-20 23:22:415215 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:475216 EXPECT_EQ(ERR_IO_PENDING, rv);
5217
5218 rv = callback.WaitForResult();
5219 EXPECT_EQ(OK, rv);
5220}
5221
[email protected]9ef1d98e2012-02-14 00:34:125222// http://crbug.com/112682
[email protected]ee0b1012012-02-04 04:30:255223#if defined(OS_MACOSX)
[email protected]9ef1d98e2012-02-14 00:34:125224#define MAYBE_SOCKS4_HTTP_GET DISABLED_SOCKS4_HTTP_GET
[email protected]ee0b1012012-02-04 04:30:255225#else
5226#define MAYBE_SOCKS4_HTTP_GET SOCKS4_HTTP_GET
5227#endif
5228
5229TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275230 HttpRequestInfo request;
5231 request.method = "GET";
5232 request.url = GURL("http://www.google.com/");
5233 request.load_flags = 0;
5234
[email protected]80d6524d2009-08-18 03:58:095235 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005236 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025237
5238 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435239 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025240
[email protected]3cd17242009-06-23 02:59:025241 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5242 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5243
5244 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355245 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025246 MockWrite("GET / HTTP/1.1\r\n"
5247 "Host: www.google.com\r\n"
5248 "Connection: keep-alive\r\n\r\n")
5249 };
5250
5251 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595252 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025253 MockRead("HTTP/1.0 200 OK\r\n"),
5254 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5255 MockRead("Payload"),
5256 MockRead(false, OK)
5257 };
5258
[email protected]31a2bfe2010-02-09 08:03:395259 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5260 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595261 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025262
[email protected]49639fa2011-12-20 23:22:415263 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025264
[email protected]49639fa2011-12-20 23:22:415265 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025266 EXPECT_EQ(ERR_IO_PENDING, rv);
5267
5268 rv = callback.WaitForResult();
5269 EXPECT_EQ(OK, rv);
5270
5271 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505272 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025273
5274 std::string response_text;
5275 rv = ReadTransaction(trans.get(), &response_text);
5276 EXPECT_EQ(OK, rv);
5277 EXPECT_EQ("Payload", response_text);
5278}
5279
[email protected]9ef1d98e2012-02-14 00:34:125280// http://crbug.com/112682
[email protected]ee0b1012012-02-04 04:30:255281#if defined(OS_MACOSX)
[email protected]9ef1d98e2012-02-14 00:34:125282#define MAYBE_SOCKS4_SSL_GET DISABLED_SOCKS4_SSL_GET
[email protected]ee0b1012012-02-04 04:30:255283#else
5284#define MAYBE_SOCKS4_SSL_GET SOCKS4_SSL_GET
5285#endif
5286
5287TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275288 HttpRequestInfo request;
5289 request.method = "GET";
5290 request.url = GURL("https://www.google.com/");
5291 request.load_flags = 0;
5292
[email protected]80d6524d2009-08-18 03:58:095293 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005294 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025295
5296 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435297 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025298
[email protected]3cd17242009-06-23 02:59:025299 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5300 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5301
5302 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355303 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5304 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025305 MockWrite("GET / HTTP/1.1\r\n"
5306 "Host: www.google.com\r\n"
5307 "Connection: keep-alive\r\n\r\n")
5308 };
5309
5310 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355311 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5312 arraysize(read_buffer)),
5313 MockRead("HTTP/1.0 200 OK\r\n"),
5314 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5315 MockRead("Payload"),
5316 MockRead(false, OK)
5317 };
5318
[email protected]31a2bfe2010-02-09 08:03:395319 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5320 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595321 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355322
[email protected]5ecc992a42009-11-11 01:41:595323 SSLSocketDataProvider ssl(true, OK);
5324 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355325
[email protected]49639fa2011-12-20 23:22:415326 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355327
[email protected]49639fa2011-12-20 23:22:415328 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355329 EXPECT_EQ(ERR_IO_PENDING, rv);
5330
5331 rv = callback.WaitForResult();
5332 EXPECT_EQ(OK, rv);
5333
5334 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505335 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355336
5337 std::string response_text;
5338 rv = ReadTransaction(trans.get(), &response_text);
5339 EXPECT_EQ(OK, rv);
5340 EXPECT_EQ("Payload", response_text);
5341}
5342
5343TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275344 HttpRequestInfo request;
5345 request.method = "GET";
5346 request.url = GURL("http://www.google.com/");
5347 request.load_flags = 0;
5348
[email protected]80d6524d2009-08-18 03:58:095349 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005350 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355351
5352 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435353 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355354
[email protected]e0c27be2009-07-15 13:09:355355 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5356 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375357 const char kSOCKS5OkRequest[] = {
5358 0x05, // Version
5359 0x01, // Command (CONNECT)
5360 0x00, // Reserved.
5361 0x03, // Address type (DOMAINNAME).
5362 0x0E, // Length of domain (14)
5363 // Domain string:
5364 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5365 0x00, 0x50, // 16-bit port (80)
5366 };
[email protected]e0c27be2009-07-15 13:09:355367 const char kSOCKS5OkResponse[] =
5368 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5369
5370 MockWrite data_writes[] = {
5371 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5372 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5373 MockWrite("GET / HTTP/1.1\r\n"
5374 "Host: www.google.com\r\n"
5375 "Connection: keep-alive\r\n\r\n")
5376 };
5377
5378 MockRead data_reads[] = {
5379 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5380 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5381 MockRead("HTTP/1.0 200 OK\r\n"),
5382 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5383 MockRead("Payload"),
5384 MockRead(false, OK)
5385 };
5386
[email protected]31a2bfe2010-02-09 08:03:395387 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5388 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595389 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355390
[email protected]49639fa2011-12-20 23:22:415391 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355392
[email protected]49639fa2011-12-20 23:22:415393 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355394 EXPECT_EQ(ERR_IO_PENDING, rv);
5395
5396 rv = callback.WaitForResult();
5397 EXPECT_EQ(OK, rv);
5398
5399 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505400 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355401
5402 std::string response_text;
5403 rv = ReadTransaction(trans.get(), &response_text);
5404 EXPECT_EQ(OK, rv);
5405 EXPECT_EQ("Payload", response_text);
5406}
5407
5408TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275409 HttpRequestInfo request;
5410 request.method = "GET";
5411 request.url = GURL("https://www.google.com/");
5412 request.load_flags = 0;
5413
[email protected]80d6524d2009-08-18 03:58:095414 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005415 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355416
5417 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435418 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355419
[email protected]e0c27be2009-07-15 13:09:355420 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5421 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375422 const unsigned char kSOCKS5OkRequest[] = {
5423 0x05, // Version
5424 0x01, // Command (CONNECT)
5425 0x00, // Reserved.
5426 0x03, // Address type (DOMAINNAME).
5427 0x0E, // Length of domain (14)
5428 // Domain string:
5429 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5430 0x01, 0xBB, // 16-bit port (443)
5431 };
5432
[email protected]e0c27be2009-07-15 13:09:355433 const char kSOCKS5OkResponse[] =
5434 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5435
5436 MockWrite data_writes[] = {
5437 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5438 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5439 arraysize(kSOCKS5OkRequest)),
5440 MockWrite("GET / HTTP/1.1\r\n"
5441 "Host: www.google.com\r\n"
5442 "Connection: keep-alive\r\n\r\n")
5443 };
5444
5445 MockRead data_reads[] = {
5446 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5447 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025448 MockRead("HTTP/1.0 200 OK\r\n"),
5449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5450 MockRead("Payload"),
5451 MockRead(false, OK)
5452 };
5453
[email protected]31a2bfe2010-02-09 08:03:395454 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5455 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595456 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025457
[email protected]5ecc992a42009-11-11 01:41:595458 SSLSocketDataProvider ssl(true, OK);
5459 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025460
[email protected]49639fa2011-12-20 23:22:415461 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025462
[email protected]49639fa2011-12-20 23:22:415463 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025464 EXPECT_EQ(ERR_IO_PENDING, rv);
5465
5466 rv = callback.WaitForResult();
5467 EXPECT_EQ(OK, rv);
5468
5469 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505470 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025471
5472 std::string response_text;
5473 rv = ReadTransaction(trans.get(), &response_text);
5474 EXPECT_EQ(OK, rv);
5475 EXPECT_EQ("Payload", response_text);
5476}
5477
[email protected]04e5be32009-06-26 20:00:315478// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065479
5480struct GroupNameTest {
5481 std::string proxy_server;
5482 std::string url;
5483 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185484 bool ssl;
[email protected]2d731a32010-04-29 01:04:065485};
5486
5487scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025488 SessionDependencies* session_deps) {
5489 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065490
[email protected]17291a022011-10-10 07:32:535491 HttpServerProperties* http_server_properties =
5492 session->http_server_properties();
5493 http_server_properties->SetAlternateProtocol(
[email protected]2d731a32010-04-29 01:04:065494 HostPortPair("host.with.alternate", 80), 443,
[email protected]8d2f7012012-02-16 00:08:045495 NPN_SPDY_21);
[email protected]2d731a32010-04-29 01:04:065496
5497 return session;
5498}
5499
5500int GroupNameTransactionHelper(
5501 const std::string& url,
5502 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065503 HttpRequestInfo request;
5504 request.method = "GET";
5505 request.url = GURL(url);
5506 request.load_flags = 0;
5507
[email protected]cb9bf6ca2011-01-28 13:15:275508 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5509
[email protected]49639fa2011-12-20 23:22:415510 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:065511
5512 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:415513 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:065514}
5515
5516TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5517 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315518 {
[email protected]2d731a32010-04-29 01:04:065519 "", // unused
[email protected]04e5be32009-06-26 20:00:315520 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545521 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185522 false,
[email protected]2ff8b312010-04-26 22:20:545523 },
5524 {
[email protected]2d731a32010-04-29 01:04:065525 "", // unused
[email protected]2ff8b312010-04-26 22:20:545526 "http://[2001:1418:13:1::25]/direct",
5527 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185528 false,
[email protected]04e5be32009-06-26 20:00:315529 },
[email protected]04e5be32009-06-26 20:00:315530
5531 // SSL Tests
5532 {
[email protected]2d731a32010-04-29 01:04:065533 "", // unused
[email protected]04e5be32009-06-26 20:00:315534 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025535 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185536 true,
[email protected]04e5be32009-06-26 20:00:315537 },
5538 {
[email protected]2d731a32010-04-29 01:04:065539 "", // unused
5540 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025541 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185542 true,
[email protected]04e5be32009-06-26 20:00:315543 },
5544 {
[email protected]2d731a32010-04-29 01:04:065545 "", // unused
[email protected]2ff8b312010-04-26 22:20:545546 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025547 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185548 true,
[email protected]2ff8b312010-04-26 22:20:545549 },
[email protected]2d731a32010-04-29 01:04:065550 };
[email protected]2ff8b312010-04-26 22:20:545551
[email protected]8e6441ca2010-08-19 05:56:385552 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065553
5554 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025555 SessionDependencies session_deps(
5556 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065557 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025558 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065559
5560 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285561 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5562 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135563 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345564 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025565 MockClientSocketPoolManager* mock_pool_manager =
5566 new MockClientSocketPoolManager;
5567 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
5568 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
5569 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065570
5571 EXPECT_EQ(ERR_IO_PENDING,
5572 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185573 if (tests[i].ssl)
5574 EXPECT_EQ(tests[i].expected_group_name,
5575 ssl_conn_pool->last_group_name_received());
5576 else
5577 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285578 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065579 }
5580
[email protected]8e6441ca2010-08-19 05:56:385581 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065582}
5583
5584TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5585 const GroupNameTest tests[] = {
5586 {
5587 "http_proxy",
5588 "http://www.google.com/http_proxy_normal",
5589 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185590 false,
[email protected]2d731a32010-04-29 01:04:065591 },
5592
5593 // SSL Tests
5594 {
5595 "http_proxy",
5596 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025597 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185598 true,
[email protected]2d731a32010-04-29 01:04:065599 },
[email protected]af3490e2010-10-16 21:02:295600
[email protected]9faeded92010-04-29 20:03:055601 {
5602 "http_proxy",
5603 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025604 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185605 true,
[email protected]9faeded92010-04-29 20:03:055606 },
[email protected]2d731a32010-04-29 01:04:065607 };
5608
[email protected]8e6441ca2010-08-19 05:56:385609 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065610
5611 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025612 SessionDependencies session_deps(
5613 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065614 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025615 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065616
5617 HttpNetworkSessionPeer peer(session);
5618
[email protected]e60e47a2010-07-14 03:37:185619 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135620 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345621 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135622 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345623 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025624
5625 MockClientSocketPoolManager* mock_pool_manager =
5626 new MockClientSocketPoolManager;
5627 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
5628 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5629 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065630
5631 EXPECT_EQ(ERR_IO_PENDING,
5632 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185633 if (tests[i].ssl)
5634 EXPECT_EQ(tests[i].expected_group_name,
5635 ssl_conn_pool->last_group_name_received());
5636 else
5637 EXPECT_EQ(tests[i].expected_group_name,
5638 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065639 }
5640
[email protected]8e6441ca2010-08-19 05:56:385641 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065642}
5643
5644TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5645 const GroupNameTest tests[] = {
5646 {
5647 "socks4://socks_proxy:1080",
5648 "http://www.google.com/socks4_direct",
5649 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185650 false,
[email protected]2d731a32010-04-29 01:04:065651 },
5652 {
5653 "socks5://socks_proxy:1080",
5654 "http://www.google.com/socks5_direct",
5655 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185656 false,
[email protected]2d731a32010-04-29 01:04:065657 },
5658
5659 // SSL Tests
5660 {
5661 "socks4://socks_proxy:1080",
5662 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025663 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185664 true,
[email protected]2d731a32010-04-29 01:04:065665 },
5666 {
5667 "socks5://socks_proxy:1080",
5668 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025669 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185670 true,
[email protected]2d731a32010-04-29 01:04:065671 },
[email protected]af3490e2010-10-16 21:02:295672
[email protected]9faeded92010-04-29 20:03:055673 {
5674 "socks4://socks_proxy:1080",
5675 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025676 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185677 true,
[email protected]9faeded92010-04-29 20:03:055678 },
[email protected]04e5be32009-06-26 20:00:315679 };
5680
[email protected]8e6441ca2010-08-19 05:56:385681 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545682
[email protected]04e5be32009-06-26 20:00:315683 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025684 SessionDependencies session_deps(
5685 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065686 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025687 SetupSessionForGroupNameTests(&session_deps));
5688
[email protected]2d731a32010-04-29 01:04:065689 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315690
[email protected]e60e47a2010-07-14 03:37:185691 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135692 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345693 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135694 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345695 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025696
5697 MockClientSocketPoolManager* mock_pool_manager =
5698 new MockClientSocketPoolManager;
5699 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
5700 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5701 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]04e5be32009-06-26 20:00:315702
[email protected]5695b8c2009-09-30 21:36:435703 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315704
[email protected]2d731a32010-04-29 01:04:065705 EXPECT_EQ(ERR_IO_PENDING,
5706 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185707 if (tests[i].ssl)
5708 EXPECT_EQ(tests[i].expected_group_name,
5709 ssl_conn_pool->last_group_name_received());
5710 else
5711 EXPECT_EQ(tests[i].expected_group_name,
5712 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315713 }
[email protected]2ff8b312010-04-26 22:20:545714
[email protected]8e6441ca2010-08-19 05:56:385715 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315716}
5717
[email protected]9172a982009-06-06 00:30:255718TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275719 HttpRequestInfo request;
5720 request.method = "GET";
5721 request.url = GURL("http://www.google.com/");
5722
[email protected]5c6a17e2009-06-10 00:54:545723 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005724 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325725
[email protected]69719062010-01-05 20:09:215726 // This simulates failure resolving all hostnames; that means we will fail
5727 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325728 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5729
[email protected]9172a982009-06-06 00:30:255730 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435731 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255732
[email protected]49639fa2011-12-20 23:22:415733 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:255734
[email protected]49639fa2011-12-20 23:22:415735 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:255736 EXPECT_EQ(ERR_IO_PENDING, rv);
5737
[email protected]9172a982009-06-06 00:30:255738 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015739 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255740}
5741
[email protected]685af592010-05-11 19:31:245742// Base test to make sure that when the load flags for a request specify to
5743// bypass the cache, the DNS cache is not used.
5744void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275745 // Issue a request, asking to bypass the cache(s).
5746 HttpRequestInfo request;
5747 request.method = "GET";
5748 request.load_flags = load_flags;
5749 request.url = GURL("http://www.google.com/");
5750
[email protected]3b9cca42009-06-16 01:08:285751 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325752
[email protected]a2c2fb92009-07-18 07:31:045753 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545754 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325755
[email protected]3b9cca42009-06-16 01:08:285756 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435757 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285758
[email protected]6e78dfb2011-07-28 21:34:475759 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285760 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:295761 TestCompletionCallback callback;
[email protected]94a0d3d92009-06-27 01:50:145762 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105763 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295764 callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:475765 EXPECT_EQ(ERR_IO_PENDING, rv);
5766 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285767 EXPECT_EQ(OK, rv);
5768
5769 // Verify that it was added to host cache, by doing a subsequent async lookup
5770 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465771 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105772 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295773 callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325774 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285775
5776 // Inject a failure the next time that "www.google.com" is resolved. This way
5777 // we can tell if the next lookup hit the cache, or the "network".
5778 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325779 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285780
5781 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5782 // first read -- this won't be reached as the host resolution will fail first.
5783 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395784 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595785 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285786
[email protected]3b9cca42009-06-16 01:08:285787 // Run the request.
[email protected]49639fa2011-12-20 23:22:415788 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285789 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:415790 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285791
5792 // If we bypassed the cache, we would have gotten a failure while resolving
5793 // "www.google.com".
5794 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5795}
5796
[email protected]685af592010-05-11 19:31:245797// There are multiple load flags that should trigger the host cache bypass.
5798// Test each in isolation:
5799TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5800 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5801}
5802
5803TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5804 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5805}
5806
5807TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5808 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5809}
5810
[email protected]0877e3d2009-10-17 22:29:575811// Make sure we can handle an error when writing the request.
5812TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5813 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275814 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575815
5816 HttpRequestInfo request;
5817 request.method = "GET";
5818 request.url = GURL("http://www.foo.com/");
5819 request.load_flags = 0;
5820
5821 MockWrite write_failure[] = {
5822 MockWrite(true, ERR_CONNECTION_RESET),
5823 };
[email protected]31a2bfe2010-02-09 08:03:395824 StaticSocketDataProvider data(NULL, 0,
5825 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595826 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575827
[email protected]49639fa2011-12-20 23:22:415828 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575829
5830 scoped_ptr<HttpTransaction> trans(
5831 new HttpNetworkTransaction(CreateSession(&session_deps)));
5832
[email protected]49639fa2011-12-20 23:22:415833 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575834 EXPECT_EQ(ERR_IO_PENDING, rv);
5835
5836 rv = callback.WaitForResult();
5837 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5838}
5839
5840// Check that a connection closed after the start of the headers finishes ok.
5841TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5842 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275843 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575844
5845 HttpRequestInfo request;
5846 request.method = "GET";
5847 request.url = GURL("http://www.foo.com/");
5848 request.load_flags = 0;
5849
5850 MockRead data_reads[] = {
5851 MockRead("HTTP/1."),
5852 MockRead(false, OK),
5853 };
5854
[email protected]31a2bfe2010-02-09 08:03:395855 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595856 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575857
[email protected]49639fa2011-12-20 23:22:415858 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575859
5860 scoped_ptr<HttpTransaction> trans(
5861 new HttpNetworkTransaction(CreateSession(&session_deps)));
5862
[email protected]49639fa2011-12-20 23:22:415863 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575864 EXPECT_EQ(ERR_IO_PENDING, rv);
5865
5866 rv = callback.WaitForResult();
5867 EXPECT_EQ(OK, rv);
5868
5869 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505870 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:575871
5872 EXPECT_TRUE(response->headers != NULL);
5873 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5874
5875 std::string response_data;
5876 rv = ReadTransaction(trans.get(), &response_data);
5877 EXPECT_EQ(OK, rv);
5878 EXPECT_EQ("", response_data);
5879}
5880
5881// Make sure that a dropped connection while draining the body for auth
5882// restart does the right thing.
5883TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5884 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275885 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575886
5887 HttpRequestInfo request;
5888 request.method = "GET";
5889 request.url = GURL("http://www.google.com/");
5890 request.load_flags = 0;
5891
5892 MockWrite data_writes1[] = {
5893 MockWrite("GET / HTTP/1.1\r\n"
5894 "Host: www.google.com\r\n"
5895 "Connection: keep-alive\r\n\r\n"),
5896 };
5897
5898 MockRead data_reads1[] = {
5899 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5900 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5901 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5902 MockRead("Content-Length: 14\r\n\r\n"),
5903 MockRead("Unauth"),
5904 MockRead(true, ERR_CONNECTION_RESET),
5905 };
5906
[email protected]31a2bfe2010-02-09 08:03:395907 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5908 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595909 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575910
5911 // After calling trans->RestartWithAuth(), this is the request we should
5912 // be issuing -- the final header line contains the credentials.
5913 MockWrite data_writes2[] = {
5914 MockWrite("GET / HTTP/1.1\r\n"
5915 "Host: www.google.com\r\n"
5916 "Connection: keep-alive\r\n"
5917 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5918 };
5919
5920 // Lastly, the server responds with the actual content.
5921 MockRead data_reads2[] = {
5922 MockRead("HTTP/1.1 200 OK\r\n"),
5923 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5924 MockRead("Content-Length: 100\r\n\r\n"),
5925 MockRead(false, OK),
5926 };
5927
[email protected]31a2bfe2010-02-09 08:03:395928 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5929 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595930 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575931
[email protected]49639fa2011-12-20 23:22:415932 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:575933
[email protected]0b0bf032010-09-21 18:08:505934 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5935
[email protected]49639fa2011-12-20 23:22:415936 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575937 EXPECT_EQ(ERR_IO_PENDING, rv);
5938
5939 rv = callback1.WaitForResult();
5940 EXPECT_EQ(OK, rv);
5941
5942 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505943 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:045944 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:575945
[email protected]49639fa2011-12-20 23:22:415946 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:575947
[email protected]49639fa2011-12-20 23:22:415948 rv = trans->RestartWithAuth(
5949 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:575950 EXPECT_EQ(ERR_IO_PENDING, rv);
5951
5952 rv = callback2.WaitForResult();
5953 EXPECT_EQ(OK, rv);
5954
5955 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505956 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:575957 EXPECT_TRUE(response->auth_challenge.get() == NULL);
5958 EXPECT_EQ(100, response->headers->GetContentLength());
5959}
5960
5961// Test HTTPS connections going through a proxy that sends extra data.
5962TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:005963 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:575964
5965 HttpRequestInfo request;
5966 request.method = "GET";
5967 request.url = GURL("https://www.google.com/");
5968 request.load_flags = 0;
5969
5970 MockRead proxy_reads[] = {
5971 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
5972 MockRead(false, OK)
5973 };
5974
[email protected]31a2bfe2010-02-09 08:03:395975 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595976 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:575977
[email protected]5ecc992a42009-11-11 01:41:595978 session_deps.socket_factory.AddSocketDataProvider(&data);
5979 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:575980
[email protected]49639fa2011-12-20 23:22:415981 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575982
5983 session_deps.socket_factory.ResetNextMockIndexes();
5984
5985 scoped_ptr<HttpTransaction> trans(
5986 new HttpNetworkTransaction(CreateSession(&session_deps)));
5987
[email protected]49639fa2011-12-20 23:22:415988 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575989 EXPECT_EQ(ERR_IO_PENDING, rv);
5990
5991 rv = callback.WaitForResult();
5992 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
5993}
5994
[email protected]e22e1362009-11-23 21:31:125995TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:465996 HttpRequestInfo request;
5997 request.method = "GET";
5998 request.url = GURL("http://www.google.com/");
5999 request.load_flags = 0;
6000
[email protected]cb9bf6ca2011-01-28 13:15:276001 SessionDependencies session_deps;
6002 scoped_ptr<HttpTransaction> trans(
6003 new HttpNetworkTransaction(CreateSession(&session_deps)));
6004
[email protected]e22e1362009-11-23 21:31:126005 MockRead data_reads[] = {
6006 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6007 MockRead(false, OK),
6008 };
[email protected]9492e4a2010-02-24 00:58:466009
6010 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6011 session_deps.socket_factory.AddSocketDataProvider(&data);
6012
[email protected]49639fa2011-12-20 23:22:416013 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:466014
[email protected]49639fa2011-12-20 23:22:416015 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466016 EXPECT_EQ(ERR_IO_PENDING, rv);
6017
6018 EXPECT_EQ(OK, callback.WaitForResult());
6019
6020 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506021 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:466022
6023 EXPECT_TRUE(response->headers != NULL);
6024 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6025
6026 std::string response_data;
6027 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f001bd6a2011-12-08 04:31:376028 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126029}
6030
[email protected]95d88ffe2010-02-04 21:25:336031TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336032 HttpRequestInfo request;
6033 request.method = "POST";
6034 request.url = GURL("http://www.google.com/upload");
6035 request.upload_data = new UploadData;
6036 request.load_flags = 0;
6037
[email protected]cb9bf6ca2011-01-28 13:15:276038 SessionDependencies session_deps;
6039 scoped_ptr<HttpTransaction> trans(
6040 new HttpNetworkTransaction(CreateSession(&session_deps)));
6041
[email protected]95d88ffe2010-02-04 21:25:336042 FilePath temp_file_path;
6043 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6044 const uint64 kFakeSize = 100000; // file is actually blank
6045
6046 std::vector<UploadData::Element> elements;
6047 UploadData::Element element;
6048 element.SetToFilePath(temp_file_path);
6049 element.SetContentLength(kFakeSize);
6050 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536051 request.upload_data->SetElements(elements);
[email protected]1dce7082012-02-10 07:39:116052 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLengthSync());
[email protected]95d88ffe2010-02-04 21:25:336053
6054 MockRead data_reads[] = {
6055 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6056 MockRead("hello world"),
6057 MockRead(false, OK),
6058 };
[email protected]31a2bfe2010-02-09 08:03:396059 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336060 session_deps.socket_factory.AddSocketDataProvider(&data);
6061
[email protected]49639fa2011-12-20 23:22:416062 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:336063
[email protected]49639fa2011-12-20 23:22:416064 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336065 EXPECT_EQ(ERR_IO_PENDING, rv);
6066
6067 rv = callback.WaitForResult();
6068 EXPECT_EQ(OK, rv);
6069
6070 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506071 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:336072
6073 EXPECT_TRUE(response->headers != NULL);
6074 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6075
6076 std::string response_data;
6077 rv = ReadTransaction(trans.get(), &response_data);
6078 EXPECT_EQ(OK, rv);
6079 EXPECT_EQ("hello world", response_data);
6080
6081 file_util::Delete(temp_file_path, false);
6082}
6083
[email protected]6624b4622010-03-29 19:58:366084TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276085 HttpRequestInfo request;
6086 request.method = "POST";
6087 request.url = GURL("http://www.google.com/upload");
6088 request.upload_data = new UploadData;
6089 request.load_flags = 0;
6090
[email protected]6624b4622010-03-29 19:58:366091 // If we try to upload an unreadable file, the network stack should report
6092 // the file size as zero and upload zero bytes for that file.
6093 SessionDependencies session_deps;
6094 scoped_ptr<HttpTransaction> trans(
6095 new HttpNetworkTransaction(CreateSession(&session_deps)));
6096
6097 FilePath temp_file;
6098 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6099 std::string temp_file_content("Unreadable file.");
6100 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6101 temp_file_content.length()));
6102 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6103
[email protected]6624b4622010-03-29 19:58:366104 std::vector<UploadData::Element> elements;
6105 UploadData::Element element;
6106 element.SetToFilePath(temp_file);
6107 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536108 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366109
6110 MockRead data_reads[] = {
6111 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6112 MockRead(false, OK),
6113 };
6114 MockWrite data_writes[] = {
6115 MockWrite("POST /upload HTTP/1.1\r\n"
6116 "Host: www.google.com\r\n"
6117 "Connection: keep-alive\r\n"
6118 "Content-Length: 0\r\n\r\n"),
6119 MockWrite(false, OK),
6120 };
6121 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6122 arraysize(data_writes));
6123 session_deps.socket_factory.AddSocketDataProvider(&data);
6124
[email protected]49639fa2011-12-20 23:22:416125 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:366126
[email protected]49639fa2011-12-20 23:22:416127 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366128 EXPECT_EQ(ERR_IO_PENDING, rv);
6129
6130 rv = callback.WaitForResult();
6131 EXPECT_EQ(OK, rv);
6132
6133 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506134 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366135 EXPECT_TRUE(response->headers != NULL);
6136 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6137
6138 file_util::Delete(temp_file, false);
6139}
6140
6141TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276142 HttpRequestInfo request;
6143 request.method = "POST";
6144 request.url = GURL("http://www.google.com/upload");
6145 request.upload_data = new UploadData;
6146 request.load_flags = 0;
6147
[email protected]6624b4622010-03-29 19:58:366148 SessionDependencies session_deps;
6149 scoped_ptr<HttpTransaction> trans(
6150 new HttpNetworkTransaction(CreateSession(&session_deps)));
6151
6152 FilePath temp_file;
6153 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6154 std::string temp_file_contents("Unreadable file.");
6155 std::string unreadable_contents(temp_file_contents.length(), '\0');
6156 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6157 temp_file_contents.length()));
6158
[email protected]6624b4622010-03-29 19:58:366159 std::vector<UploadData::Element> elements;
6160 UploadData::Element element;
6161 element.SetToFilePath(temp_file);
6162 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536163 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366164
6165 MockRead data_reads[] = {
6166 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6167 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6168 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6169
6170 MockRead("HTTP/1.1 200 OK\r\n"),
6171 MockRead("Content-Length: 0\r\n\r\n"),
6172 MockRead(false, OK),
6173 };
6174 MockWrite data_writes[] = {
6175 MockWrite("POST /upload HTTP/1.1\r\n"
6176 "Host: www.google.com\r\n"
6177 "Connection: keep-alive\r\n"
6178 "Content-Length: 16\r\n\r\n"),
6179 MockWrite(false, temp_file_contents.c_str()),
6180
6181 MockWrite("POST /upload HTTP/1.1\r\n"
6182 "Host: www.google.com\r\n"
6183 "Connection: keep-alive\r\n"
6184 "Content-Length: 16\r\n"
6185 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6186 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6187 MockWrite(false, OK),
6188 };
6189 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6190 arraysize(data_writes));
6191 session_deps.socket_factory.AddSocketDataProvider(&data);
6192
[email protected]49639fa2011-12-20 23:22:416193 TestCompletionCallback callback1;
[email protected]6624b4622010-03-29 19:58:366194
[email protected]49639fa2011-12-20 23:22:416195 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366196 EXPECT_EQ(ERR_IO_PENDING, rv);
6197
6198 rv = callback1.WaitForResult();
6199 EXPECT_EQ(OK, rv);
6200
6201 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:046202 ASSERT_TRUE(response != NULL);
6203 ASSERT_TRUE(response->headers != NULL);
[email protected]6624b4622010-03-29 19:58:366204 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
[email protected]79cb5c12011-09-12 13:12:046205 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]6624b4622010-03-29 19:58:366206
6207 // Now make the file unreadable and try again.
6208 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6209
[email protected]49639fa2011-12-20 23:22:416210 TestCompletionCallback callback2;
[email protected]6624b4622010-03-29 19:58:366211
[email protected]49639fa2011-12-20 23:22:416212 rv = trans->RestartWithAuth(
6213 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]6624b4622010-03-29 19:58:366214 EXPECT_EQ(ERR_IO_PENDING, rv);
6215
6216 rv = callback2.WaitForResult();
6217 EXPECT_EQ(OK, rv);
6218
6219 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506220 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366221 EXPECT_TRUE(response->headers != NULL);
6222 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6223 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6224
6225 file_util::Delete(temp_file, false);
6226}
6227
[email protected]aeefc9e82010-02-19 16:18:276228// Tests that changes to Auth realms are treated like auth rejections.
6229TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6230 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276231
6232 HttpRequestInfo request;
6233 request.method = "GET";
6234 request.url = GURL("http://www.google.com/");
6235 request.load_flags = 0;
6236
6237 // First transaction will request a resource and receive a Basic challenge
6238 // with realm="first_realm".
6239 MockWrite data_writes1[] = {
6240 MockWrite("GET / HTTP/1.1\r\n"
6241 "Host: www.google.com\r\n"
6242 "Connection: keep-alive\r\n"
6243 "\r\n"),
6244 };
6245 MockRead data_reads1[] = {
6246 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6247 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6248 "\r\n"),
6249 };
6250
6251 // After calling trans->RestartWithAuth(), provide an Authentication header
6252 // for first_realm. The server will reject and provide a challenge with
6253 // second_realm.
6254 MockWrite data_writes2[] = {
6255 MockWrite("GET / HTTP/1.1\r\n"
6256 "Host: www.google.com\r\n"
6257 "Connection: keep-alive\r\n"
6258 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6259 "\r\n"),
6260 };
6261 MockRead data_reads2[] = {
6262 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6263 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6264 "\r\n"),
6265 };
6266
6267 // This again fails, and goes back to first_realm. Make sure that the
6268 // entry is removed from cache.
6269 MockWrite data_writes3[] = {
6270 MockWrite("GET / HTTP/1.1\r\n"
6271 "Host: www.google.com\r\n"
6272 "Connection: keep-alive\r\n"
6273 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6274 "\r\n"),
6275 };
6276 MockRead data_reads3[] = {
6277 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6278 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6279 "\r\n"),
6280 };
6281
6282 // Try one last time (with the correct password) and get the resource.
6283 MockWrite data_writes4[] = {
6284 MockWrite("GET / HTTP/1.1\r\n"
6285 "Host: www.google.com\r\n"
6286 "Connection: keep-alive\r\n"
6287 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6288 "\r\n"),
6289 };
6290 MockRead data_reads4[] = {
6291 MockRead("HTTP/1.1 200 OK\r\n"
6292 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506293 "Content-Length: 5\r\n"
6294 "\r\n"
6295 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276296 };
6297
6298 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6299 data_writes1, arraysize(data_writes1));
6300 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6301 data_writes2, arraysize(data_writes2));
6302 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6303 data_writes3, arraysize(data_writes3));
6304 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6305 data_writes4, arraysize(data_writes4));
6306 session_deps.socket_factory.AddSocketDataProvider(&data1);
6307 session_deps.socket_factory.AddSocketDataProvider(&data2);
6308 session_deps.socket_factory.AddSocketDataProvider(&data3);
6309 session_deps.socket_factory.AddSocketDataProvider(&data4);
6310
[email protected]49639fa2011-12-20 23:22:416311 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:276312
[email protected]0b0bf032010-09-21 18:08:506313 scoped_ptr<HttpTransaction> trans(
6314 new HttpNetworkTransaction(CreateSession(&session_deps)));
6315
[email protected]aeefc9e82010-02-19 16:18:276316 // Issue the first request with Authorize headers. There should be a
6317 // password prompt for first_realm waiting to be filled in after the
6318 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416319 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276320 EXPECT_EQ(ERR_IO_PENDING, rv);
6321 rv = callback1.WaitForResult();
6322 EXPECT_EQ(OK, rv);
6323 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506324 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046325 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6326 ASSERT_FALSE(challenge == NULL);
6327 EXPECT_FALSE(challenge->is_proxy);
6328 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6329 EXPECT_EQ("first_realm", challenge->realm);
6330 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276331
6332 // Issue the second request with an incorrect password. There should be a
6333 // password prompt for second_realm waiting to be filled in after the
6334 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416335 TestCompletionCallback callback2;
6336 rv = trans->RestartWithAuth(
6337 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:276338 EXPECT_EQ(ERR_IO_PENDING, rv);
6339 rv = callback2.WaitForResult();
6340 EXPECT_EQ(OK, rv);
6341 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506342 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046343 challenge = response->auth_challenge.get();
6344 ASSERT_FALSE(challenge == NULL);
6345 EXPECT_FALSE(challenge->is_proxy);
6346 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6347 EXPECT_EQ("second_realm", challenge->realm);
6348 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276349
6350 // Issue the third request with another incorrect password. There should be
6351 // a password prompt for first_realm waiting to be filled in. If the password
6352 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6353 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:416354 TestCompletionCallback callback3;
6355 rv = trans->RestartWithAuth(
6356 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:276357 EXPECT_EQ(ERR_IO_PENDING, rv);
6358 rv = callback3.WaitForResult();
6359 EXPECT_EQ(OK, rv);
6360 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506361 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046362 challenge = response->auth_challenge.get();
6363 ASSERT_FALSE(challenge == NULL);
6364 EXPECT_FALSE(challenge->is_proxy);
6365 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6366 EXPECT_EQ("first_realm", challenge->realm);
6367 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276368
6369 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:416370 TestCompletionCallback callback4;
6371 rv = trans->RestartWithAuth(
6372 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:276373 EXPECT_EQ(ERR_IO_PENDING, rv);
6374 rv = callback4.WaitForResult();
6375 EXPECT_EQ(OK, rv);
6376 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506377 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:276378 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6379}
6380
[email protected]564b4912010-03-09 16:30:426381TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]5285d972011-10-18 18:56:346382 HttpStreamFactory::set_next_protos(MakeNextProtos("foo", "bar", NULL));
[email protected]8e6441ca2010-08-19 05:56:386383 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426384
[email protected]564b4912010-03-09 16:30:426385 SessionDependencies session_deps;
6386
6387 MockRead data_reads[] = {
6388 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356389 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426390 MockRead("hello world"),
6391 MockRead(false, OK),
6392 };
6393
6394 HttpRequestInfo request;
6395 request.method = "GET";
6396 request.url = GURL("http://www.google.com/");
6397 request.load_flags = 0;
6398
6399 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6400
6401 session_deps.socket_factory.AddSocketDataProvider(&data);
6402
[email protected]49639fa2011-12-20 23:22:416403 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426404
6405 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6406 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6407
[email protected]49639fa2011-12-20 23:22:416408 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426409 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536410
[email protected]2fbaecf22010-07-22 22:20:356411 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]17291a022011-10-10 07:32:536412 const HttpServerProperties& http_server_properties =
6413 *session->http_server_properties();
[email protected]564b4912010-03-09 16:30:426414 EXPECT_FALSE(
[email protected]17291a022011-10-10 07:32:536415 http_server_properties.HasAlternateProtocol(http_host_port_pair));
[email protected]564b4912010-03-09 16:30:426416
6417 EXPECT_EQ(OK, callback.WaitForResult());
6418
6419 const HttpResponseInfo* response = trans->GetResponseInfo();
6420 ASSERT_TRUE(response != NULL);
6421 ASSERT_TRUE(response->headers != NULL);
6422 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536423 EXPECT_FALSE(response->was_fetched_via_spdy);
6424 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426425
6426 std::string response_data;
6427 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6428 EXPECT_EQ("hello world", response_data);
6429
[email protected]17291a022011-10-10 07:32:536430 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6431 const PortAlternateProtocolPair alternate =
6432 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6433 PortAlternateProtocolPair expected_alternate;
[email protected]564b4912010-03-09 16:30:426434 expected_alternate.port = 443;
[email protected]8d2f7012012-02-16 00:08:046435 expected_alternate.protocol = NPN_SPDY_21;
[email protected]564b4912010-03-09 16:30:426436 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426437
[email protected]8e6441ca2010-08-19 05:56:386438 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]5285d972011-10-18 18:56:346439 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]564b4912010-03-09 16:30:426440}
6441
[email protected]8b95ed62011-03-18 18:12:036442TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386443 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426444 SessionDependencies session_deps;
6445
6446 HttpRequestInfo request;
6447 request.method = "GET";
6448 request.url = GURL("http://www.google.com/");
6449 request.load_flags = 0;
6450
6451 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6452 StaticSocketDataProvider first_data;
6453 first_data.set_connect_data(mock_connect);
6454 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6455
6456 MockRead data_reads[] = {
6457 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6458 MockRead("hello world"),
6459 MockRead(true, OK),
6460 };
6461 StaticSocketDataProvider second_data(
6462 data_reads, arraysize(data_reads), NULL, 0);
6463 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6464
[email protected]564b4912010-03-09 16:30:426465 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6466
[email protected]17291a022011-10-10 07:32:536467 HttpServerProperties* http_server_properties =
6468 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116469 // Port must be < 1024, or the header will be ignored (since initial port was
6470 // port 80 (another restricted port).
[email protected]17291a022011-10-10 07:32:536471 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116472 HostPortPair::FromURL(request.url),
6473 666 /* port is ignored by MockConnect anyway */,
[email protected]8d2f7012012-02-16 00:08:046474 NPN_SPDY_21);
[email protected]564b4912010-03-09 16:30:426475
6476 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416477 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426478
[email protected]49639fa2011-12-20 23:22:416479 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426480 EXPECT_EQ(ERR_IO_PENDING, rv);
6481 EXPECT_EQ(OK, callback.WaitForResult());
6482
6483 const HttpResponseInfo* response = trans->GetResponseInfo();
6484 ASSERT_TRUE(response != NULL);
6485 ASSERT_TRUE(response->headers != NULL);
6486 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6487
6488 std::string response_data;
6489 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6490 EXPECT_EQ("hello world", response_data);
6491
[email protected]17291a022011-10-10 07:32:536492 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116493 HostPortPair::FromURL(request.url)));
[email protected]17291a022011-10-10 07:32:536494 const PortAlternateProtocolPair alternate =
6495 http_server_properties->GetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116496 HostPortPair::FromURL(request.url));
[email protected]17291a022011-10-10 07:32:536497 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386498 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426499}
6500
[email protected]3912662a32011-10-04 00:51:116501TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6502 // Ensure that we're not allowed to redirect traffic via an alternate
6503 // protocol to an unrestricted (port >= 1024) when the original traffic was
6504 // on a restricted port (port < 1024). Ensure that we can redirect in all
6505 // other cases.
6506 HttpStreamFactory::set_use_alternate_protocols(true);
6507 SessionDependencies session_deps;
6508
6509 HttpRequestInfo restricted_port_request;
6510 restricted_port_request.method = "GET";
6511 restricted_port_request.url = GURL("http://www.google.com:1023/");
6512 restricted_port_request.load_flags = 0;
6513
6514 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6515 StaticSocketDataProvider first_data;
6516 first_data.set_connect_data(mock_connect);
6517 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6518
6519 MockRead data_reads[] = {
6520 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6521 MockRead("hello world"),
6522 MockRead(true, OK),
6523 };
6524 StaticSocketDataProvider second_data(
6525 data_reads, arraysize(data_reads), NULL, 0);
6526 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6527
6528 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6529
[email protected]17291a022011-10-10 07:32:536530 HttpServerProperties* http_server_properties =
6531 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116532 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536533 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116534 HostPortPair::FromURL(restricted_port_request.url),
6535 kUnrestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046536 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116537
6538 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416539 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116540
[email protected]49639fa2011-12-20 23:22:416541 int rv = trans->Start(
6542 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116543 EXPECT_EQ(ERR_IO_PENDING, rv);
6544 // Invalid change to unrestricted port should fail.
6545 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6546
6547 HttpStreamFactory::set_use_alternate_protocols(false);
6548}
6549
6550TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6551 // Ensure that we're not allowed to redirect traffic via an alternate
6552 // protocol to an unrestricted (port >= 1024) when the original traffic was
6553 // on a restricted port (port < 1024). Ensure that we can redirect in all
6554 // other cases.
6555 HttpStreamFactory::set_use_alternate_protocols(true);
6556 SessionDependencies session_deps;
6557
6558 HttpRequestInfo restricted_port_request;
6559 restricted_port_request.method = "GET";
6560 restricted_port_request.url = GURL("http://www.google.com:1023/");
6561 restricted_port_request.load_flags = 0;
6562
6563 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6564 StaticSocketDataProvider first_data;
6565 first_data.set_connect_data(mock_connect);
6566 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6567
6568 MockRead data_reads[] = {
6569 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6570 MockRead("hello world"),
6571 MockRead(true, OK),
6572 };
6573 StaticSocketDataProvider second_data(
6574 data_reads, arraysize(data_reads), NULL, 0);
6575 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6576
6577 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6578
[email protected]17291a022011-10-10 07:32:536579 HttpServerProperties* http_server_properties =
6580 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116581 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536582 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116583 HostPortPair::FromURL(restricted_port_request.url),
6584 kRestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046585 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116586
6587 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416588 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116589
[email protected]49639fa2011-12-20 23:22:416590 int rv = trans->Start(
6591 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116592 EXPECT_EQ(ERR_IO_PENDING, rv);
6593 // Valid change to restricted port should pass.
6594 EXPECT_EQ(OK, callback.WaitForResult());
6595
6596 HttpStreamFactory::set_use_alternate_protocols(false);
6597}
6598
6599TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6600 // Ensure that we're not allowed to redirect traffic via an alternate
6601 // protocol to an unrestricted (port >= 1024) when the original traffic was
6602 // on a restricted port (port < 1024). Ensure that we can redirect in all
6603 // other cases.
6604 HttpStreamFactory::set_use_alternate_protocols(true);
6605 SessionDependencies session_deps;
6606
6607 HttpRequestInfo unrestricted_port_request;
6608 unrestricted_port_request.method = "GET";
6609 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6610 unrestricted_port_request.load_flags = 0;
6611
6612 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6613 StaticSocketDataProvider first_data;
6614 first_data.set_connect_data(mock_connect);
6615 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6616
6617 MockRead data_reads[] = {
6618 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6619 MockRead("hello world"),
6620 MockRead(true, OK),
6621 };
6622 StaticSocketDataProvider second_data(
6623 data_reads, arraysize(data_reads), NULL, 0);
6624 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6625
6626 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6627
[email protected]17291a022011-10-10 07:32:536628 HttpServerProperties* http_server_properties =
6629 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116630 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536631 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116632 HostPortPair::FromURL(unrestricted_port_request.url),
6633 kRestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046634 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116635
6636 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416637 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116638
[email protected]49639fa2011-12-20 23:22:416639 int rv = trans->Start(
6640 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116641 EXPECT_EQ(ERR_IO_PENDING, rv);
6642 // Valid change to restricted port should pass.
6643 EXPECT_EQ(OK, callback.WaitForResult());
6644
6645 HttpStreamFactory::set_use_alternate_protocols(false);
6646}
6647
6648TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6649 // Ensure that we're not allowed to redirect traffic via an alternate
6650 // protocol to an unrestricted (port >= 1024) when the original traffic was
6651 // on a restricted port (port < 1024). Ensure that we can redirect in all
6652 // other cases.
6653 HttpStreamFactory::set_use_alternate_protocols(true);
6654 SessionDependencies session_deps;
6655
6656 HttpRequestInfo unrestricted_port_request;
6657 unrestricted_port_request.method = "GET";
6658 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6659 unrestricted_port_request.load_flags = 0;
6660
6661 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6662 StaticSocketDataProvider first_data;
6663 first_data.set_connect_data(mock_connect);
6664 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6665
6666 MockRead data_reads[] = {
6667 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6668 MockRead("hello world"),
6669 MockRead(true, OK),
6670 };
6671 StaticSocketDataProvider second_data(
6672 data_reads, arraysize(data_reads), NULL, 0);
6673 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6674
6675 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6676
[email protected]17291a022011-10-10 07:32:536677 HttpServerProperties* http_server_properties =
6678 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116679 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536680 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116681 HostPortPair::FromURL(unrestricted_port_request.url),
6682 kUnrestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046683 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116684
6685 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416686 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116687
[email protected]49639fa2011-12-20 23:22:416688 int rv = trans->Start(
6689 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116690 EXPECT_EQ(ERR_IO_PENDING, rv);
6691 // Valid change to an unrestricted port should pass.
6692 EXPECT_EQ(OK, callback.WaitForResult());
6693
6694 HttpStreamFactory::set_use_alternate_protocols(false);
6695}
6696
[email protected]eb6234e2012-01-19 01:50:026697TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
6698 // Ensure that we're not allowed to redirect traffic via an alternate
6699 // protocol to an unsafe port, and that we resume the second
6700 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
6701 HttpStreamFactory::set_use_alternate_protocols(true);
6702 SessionDependencies session_deps;
6703
6704 HttpRequestInfo request;
6705 request.method = "GET";
6706 request.url = GURL("http://www.google.com/");
6707 request.load_flags = 0;
6708
6709 // The alternate protocol request will error out before we attempt to connect,
6710 // so only the standard HTTP request will try to connect.
6711 MockRead data_reads[] = {
6712 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6713 MockRead("hello world"),
6714 MockRead(true, OK),
6715 };
6716 StaticSocketDataProvider data(
6717 data_reads, arraysize(data_reads), NULL, 0);
6718 session_deps.socket_factory.AddSocketDataProvider(&data);
6719
6720 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6721
6722 HttpServerProperties* http_server_properties =
6723 session->http_server_properties();
6724 const int kUnsafePort = 7;
6725 http_server_properties->SetAlternateProtocol(
6726 HostPortPair::FromURL(request.url),
6727 kUnsafePort,
6728 NPN_SPDY_2);
6729
6730 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6731 TestCompletionCallback callback;
6732
6733 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6734 EXPECT_EQ(ERR_IO_PENDING, rv);
6735 // The HTTP request should succeed.
6736 EXPECT_EQ(OK, callback.WaitForResult());
6737
6738 // Disable alternate protocol before the asserts.
6739 HttpStreamFactory::set_use_alternate_protocols(false);
6740
6741 const HttpResponseInfo* response = trans->GetResponseInfo();
6742 ASSERT_TRUE(response != NULL);
6743 ASSERT_TRUE(response->headers != NULL);
6744 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6745
6746 std::string response_data;
6747 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6748 EXPECT_EQ("hello world", response_data);
6749}
6750
[email protected]2ff8b312010-04-26 22:20:546751TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386752 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346753 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:546754 SessionDependencies session_deps;
6755
6756 HttpRequestInfo request;
6757 request.method = "GET";
6758 request.url = GURL("http://www.google.com/");
6759 request.load_flags = 0;
6760
6761 MockRead data_reads[] = {
6762 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356763 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546764 MockRead("hello world"),
6765 MockRead(true, OK),
6766 };
6767
6768 StaticSocketDataProvider first_transaction(
6769 data_reads, arraysize(data_reads), NULL, 0);
6770 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6771
6772 SSLSocketDataProvider ssl(true, OK);
6773 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:206774 ssl.next_proto = "spdy/2.1";
[email protected]65041fa2010-05-21 06:56:536775 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:206776 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2ff8b312010-04-26 22:20:546777 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6778
[email protected]2bd93022010-07-17 00:58:446779 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136780 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546781
[email protected]2bd93022010-07-17 00:58:446782 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6783 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546784 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136785 CreateMockRead(*resp),
6786 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546787 MockRead(true, 0, 0),
6788 };
6789
[email protected]a1595312012-01-22 03:25:046790 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:546791 new DelayedSocketData(
6792 1, // wait for one write to finish before reading.
6793 spdy_reads, arraysize(spdy_reads),
6794 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:046795 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:546796
[email protected]2d6728692011-03-12 01:39:556797 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6798 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6799 NULL, 0, NULL, 0);
6800 hanging_non_alternate_protocol_socket.set_connect_data(
6801 never_finishing_connect);
6802 session_deps.socket_factory.AddSocketDataProvider(
6803 &hanging_non_alternate_protocol_socket);
6804
[email protected]49639fa2011-12-20 23:22:416805 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:546806
6807 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6808 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6809
[email protected]49639fa2011-12-20 23:22:416810 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546811 EXPECT_EQ(ERR_IO_PENDING, rv);
6812 EXPECT_EQ(OK, callback.WaitForResult());
6813
6814 const HttpResponseInfo* response = trans->GetResponseInfo();
6815 ASSERT_TRUE(response != NULL);
6816 ASSERT_TRUE(response->headers != NULL);
6817 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6818
6819 std::string response_data;
6820 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6821 EXPECT_EQ("hello world", response_data);
6822
6823 trans.reset(new HttpNetworkTransaction(session));
6824
[email protected]49639fa2011-12-20 23:22:416825 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546826 EXPECT_EQ(ERR_IO_PENDING, rv);
6827 EXPECT_EQ(OK, callback.WaitForResult());
6828
6829 response = trans->GetResponseInfo();
6830 ASSERT_TRUE(response != NULL);
6831 ASSERT_TRUE(response->headers != NULL);
6832 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536833 EXPECT_TRUE(response->was_fetched_via_spdy);
6834 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546835
6836 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6837 EXPECT_EQ("hello!", response_data);
6838
[email protected]5285d972011-10-18 18:56:346839 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:386840 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546841}
6842
[email protected]2d6728692011-03-12 01:39:556843TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6844 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346845 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556846 SessionDependencies session_deps;
6847
6848 HttpRequestInfo request;
6849 request.method = "GET";
6850 request.url = GURL("http://www.google.com/");
6851 request.load_flags = 0;
6852
6853 MockRead data_reads[] = {
6854 MockRead("HTTP/1.1 200 OK\r\n"),
6855 MockRead(kAlternateProtocolHttpHeader),
6856 MockRead("hello world"),
6857 MockRead(true, OK),
6858 };
6859
6860 StaticSocketDataProvider first_transaction(
6861 data_reads, arraysize(data_reads), NULL, 0);
6862 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6863 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6864
6865 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6866 StaticSocketDataProvider hanging_socket(
6867 NULL, 0, NULL, 0);
6868 hanging_socket.set_connect_data(never_finishing_connect);
6869 // Socket 2 and 3 are the hanging Alternate-Protocol and
6870 // non-Alternate-Protocol jobs from the 2nd transaction.
6871 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6872 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6873
6874 SSLSocketDataProvider ssl(true, OK);
6875 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:206876 ssl.next_proto = "spdy/2.1";
[email protected]2d6728692011-03-12 01:39:556877 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:206878 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2d6728692011-03-12 01:39:556879 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6880
6881 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6882 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6883 MockWrite spdy_writes[] = {
6884 CreateMockWrite(*req1),
6885 CreateMockWrite(*req2),
6886 };
6887 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6888 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6889 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6890 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6891 MockRead spdy_reads[] = {
6892 CreateMockRead(*resp1),
6893 CreateMockRead(*data1),
6894 CreateMockRead(*resp2),
6895 CreateMockRead(*data2),
6896 MockRead(true, 0, 0),
6897 };
6898
[email protected]a1595312012-01-22 03:25:046899 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2d6728692011-03-12 01:39:556900 new DelayedSocketData(
6901 2, // wait for writes to finish before reading.
6902 spdy_reads, arraysize(spdy_reads),
6903 spdy_writes, arraysize(spdy_writes)));
6904 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]a1595312012-01-22 03:25:046905 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2d6728692011-03-12 01:39:556906
6907 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6908 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6909
6910 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]49639fa2011-12-20 23:22:416911 TestCompletionCallback callback1;
[email protected]2d6728692011-03-12 01:39:556912 HttpNetworkTransaction trans1(session);
6913
[email protected]49639fa2011-12-20 23:22:416914 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556915 EXPECT_EQ(ERR_IO_PENDING, rv);
6916 EXPECT_EQ(OK, callback1.WaitForResult());
6917
6918 const HttpResponseInfo* response = trans1.GetResponseInfo();
6919 ASSERT_TRUE(response != NULL);
6920 ASSERT_TRUE(response->headers != NULL);
6921 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6922
6923 std::string response_data;
6924 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6925 EXPECT_EQ("hello world", response_data);
6926
[email protected]49639fa2011-12-20 23:22:416927 TestCompletionCallback callback2;
[email protected]2d6728692011-03-12 01:39:556928 HttpNetworkTransaction trans2(session);
[email protected]49639fa2011-12-20 23:22:416929 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556930 EXPECT_EQ(ERR_IO_PENDING, rv);
6931
[email protected]49639fa2011-12-20 23:22:416932 TestCompletionCallback callback3;
[email protected]2d6728692011-03-12 01:39:556933 HttpNetworkTransaction trans3(session);
[email protected]49639fa2011-12-20 23:22:416934 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:556935 EXPECT_EQ(ERR_IO_PENDING, rv);
6936
6937 EXPECT_EQ(OK, callback2.WaitForResult());
6938 EXPECT_EQ(OK, callback3.WaitForResult());
6939
6940 response = trans2.GetResponseInfo();
6941 ASSERT_TRUE(response != NULL);
6942 ASSERT_TRUE(response->headers != NULL);
6943 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6944 EXPECT_TRUE(response->was_fetched_via_spdy);
6945 EXPECT_TRUE(response->was_npn_negotiated);
6946 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6947 EXPECT_EQ("hello!", response_data);
6948
6949 response = trans3.GetResponseInfo();
6950 ASSERT_TRUE(response != NULL);
6951 ASSERT_TRUE(response->headers != NULL);
6952 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6953 EXPECT_TRUE(response->was_fetched_via_spdy);
6954 EXPECT_TRUE(response->was_npn_negotiated);
6955 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6956 EXPECT_EQ("hello!", response_data);
6957
[email protected]5285d972011-10-18 18:56:346958 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:556959 HttpStreamFactory::set_use_alternate_protocols(false);
6960}
6961
6962TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6963 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346964 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556965 SessionDependencies session_deps;
6966
6967 HttpRequestInfo request;
6968 request.method = "GET";
6969 request.url = GURL("http://www.google.com/");
6970 request.load_flags = 0;
6971
6972 MockRead data_reads[] = {
6973 MockRead("HTTP/1.1 200 OK\r\n"),
6974 MockRead(kAlternateProtocolHttpHeader),
6975 MockRead("hello world"),
6976 MockRead(true, OK),
6977 };
6978
6979 StaticSocketDataProvider first_transaction(
6980 data_reads, arraysize(data_reads), NULL, 0);
6981 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6982
6983 SSLSocketDataProvider ssl(true, OK);
6984 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:206985 ssl.next_proto = "spdy/2.1";
[email protected]2d6728692011-03-12 01:39:556986 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:206987 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2d6728692011-03-12 01:39:556988 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6989
6990 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6991 StaticSocketDataProvider hanging_alternate_protocol_socket(
6992 NULL, 0, NULL, 0);
6993 hanging_alternate_protocol_socket.set_connect_data(
6994 never_finishing_connect);
6995 session_deps.socket_factory.AddSocketDataProvider(
6996 &hanging_alternate_protocol_socket);
6997
6998 // 2nd request is just a copy of the first one, over HTTP again.
6999 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7000
[email protected]49639fa2011-12-20 23:22:417001 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:557002
7003 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7004 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7005
[email protected]49639fa2011-12-20 23:22:417006 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557007 EXPECT_EQ(ERR_IO_PENDING, rv);
7008 EXPECT_EQ(OK, callback.WaitForResult());
7009
7010 const HttpResponseInfo* response = trans->GetResponseInfo();
7011 ASSERT_TRUE(response != NULL);
7012 ASSERT_TRUE(response->headers != NULL);
7013 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7014
7015 std::string response_data;
7016 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7017 EXPECT_EQ("hello world", response_data);
7018
7019 trans.reset(new HttpNetworkTransaction(session));
7020
[email protected]49639fa2011-12-20 23:22:417021 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557022 EXPECT_EQ(ERR_IO_PENDING, rv);
7023 EXPECT_EQ(OK, callback.WaitForResult());
7024
7025 response = trans->GetResponseInfo();
7026 ASSERT_TRUE(response != NULL);
7027 ASSERT_TRUE(response->headers != NULL);
7028 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7029 EXPECT_FALSE(response->was_fetched_via_spdy);
7030 EXPECT_FALSE(response->was_npn_negotiated);
7031
7032 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7033 EXPECT_EQ("hello world", response_data);
7034
[email protected]5285d972011-10-18 18:56:347035 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557036 HttpStreamFactory::set_use_alternate_protocols(false);
7037}
7038
[email protected]631f1322010-04-30 17:59:117039class CapturingProxyResolver : public ProxyResolver {
7040 public:
7041 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7042 virtual ~CapturingProxyResolver() {}
7043
7044 virtual int GetProxyForURL(const GURL& url,
7045 ProxyInfo* results,
[email protected]235786812011-12-20 02:15:317046 const CompletionCallback& callback,
[email protected]631f1322010-04-30 17:59:117047 RequestHandle* request,
7048 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:407049 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7050 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:427051 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:117052 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:427053 return OK;
[email protected]631f1322010-04-30 17:59:117054 }
7055
7056 virtual void CancelRequest(RequestHandle request) {
7057 NOTREACHED();
7058 }
7059
[email protected]f2c971f2011-11-08 00:33:177060 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
7061 NOTREACHED();
7062 return LOAD_STATE_IDLE;
7063 }
7064
7065 virtual LoadState GetLoadStateThreadSafe(
7066 RequestHandle request) const OVERRIDE {
7067 NOTREACHED();
7068 return LOAD_STATE_IDLE;
7069 }
7070
[email protected]1e605472010-12-16 21:41:407071 virtual void CancelSetPacScript() {
7072 NOTREACHED();
7073 }
7074
[email protected]24476402010-07-20 20:55:177075 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]235786812011-12-20 02:15:317076 const CompletionCallback& /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:427077 return OK;
[email protected]631f1322010-04-30 17:59:117078 }
7079
[email protected]24476402010-07-20 20:55:177080 const std::vector<GURL>& resolved() const { return resolved_; }
7081
7082 private:
[email protected]631f1322010-04-30 17:59:117083 std::vector<GURL> resolved_;
7084
7085 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7086};
7087
[email protected]631f1322010-04-30 17:59:117088TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:387089 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347090 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]631f1322010-04-30 17:59:117091
7092 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:427093 proxy_config.set_auto_detect(true);
7094 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:117095
[email protected]631f1322010-04-30 17:59:117096 CapturingProxyResolver* capturing_proxy_resolver =
7097 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:387098 SessionDependencies session_deps(new ProxyService(
7099 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7100 NULL));
[email protected]631f1322010-04-30 17:59:117101
7102 HttpRequestInfo request;
7103 request.method = "GET";
7104 request.url = GURL("http://www.google.com/");
7105 request.load_flags = 0;
7106
7107 MockRead data_reads[] = {
7108 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357109 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:117110 MockRead("hello world"),
7111 MockRead(true, OK),
7112 };
7113
7114 StaticSocketDataProvider first_transaction(
7115 data_reads, arraysize(data_reads), NULL, 0);
7116 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7117
7118 SSLSocketDataProvider ssl(true, OK);
7119 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:207120 ssl.next_proto = "spdy/2.1";
[email protected]65041fa2010-05-21 06:56:537121 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:207122 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]631f1322010-04-30 17:59:117123 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7124
[email protected]2bd93022010-07-17 00:58:447125 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:117126 MockWrite spdy_writes[] = {
7127 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7128 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:427129 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:137130 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:117131 };
7132
[email protected]d911f1b2010-05-05 22:39:427133 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7134
[email protected]2bd93022010-07-17 00:58:447135 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7136 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:117137 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:427138 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:137139 CreateMockRead(*resp.get(), 4), // 2, 4
7140 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:427141 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:117142 };
7143
[email protected]a1595312012-01-22 03:25:047144 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d911f1b2010-05-05 22:39:427145 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:117146 spdy_reads, arraysize(spdy_reads),
7147 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047148 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]631f1322010-04-30 17:59:117149
[email protected]2d6728692011-03-12 01:39:557150 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7151 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7152 NULL, 0, NULL, 0);
7153 hanging_non_alternate_protocol_socket.set_connect_data(
7154 never_finishing_connect);
7155 session_deps.socket_factory.AddSocketDataProvider(
7156 &hanging_non_alternate_protocol_socket);
7157
[email protected]49639fa2011-12-20 23:22:417158 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:117159
7160 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7161 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7162
[email protected]49639fa2011-12-20 23:22:417163 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117164 EXPECT_EQ(ERR_IO_PENDING, rv);
7165 EXPECT_EQ(OK, callback.WaitForResult());
7166
7167 const HttpResponseInfo* response = trans->GetResponseInfo();
7168 ASSERT_TRUE(response != NULL);
7169 ASSERT_TRUE(response->headers != NULL);
7170 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537171 EXPECT_FALSE(response->was_fetched_via_spdy);
7172 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117173
7174 std::string response_data;
7175 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7176 EXPECT_EQ("hello world", response_data);
7177
7178 trans.reset(new HttpNetworkTransaction(session));
7179
[email protected]49639fa2011-12-20 23:22:417180 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117181 EXPECT_EQ(ERR_IO_PENDING, rv);
7182 EXPECT_EQ(OK, callback.WaitForResult());
7183
7184 response = trans->GetResponseInfo();
7185 ASSERT_TRUE(response != NULL);
7186 ASSERT_TRUE(response->headers != NULL);
7187 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537188 EXPECT_TRUE(response->was_fetched_via_spdy);
7189 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117190
7191 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7192 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557193 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427194 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117195 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427196 EXPECT_EQ("https://www.google.com/",
7197 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117198
[email protected]5285d972011-10-18 18:56:347199 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387200 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117201}
[email protected]631f1322010-04-30 17:59:117202
[email protected]2ff8b312010-04-26 22:20:547203TEST_F(HttpNetworkTransactionTest,
7204 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387205 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347206 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:547207 SessionDependencies session_deps;
7208
7209 HttpRequestInfo request;
7210 request.method = "GET";
7211 request.url = GURL("http://www.google.com/");
7212 request.load_flags = 0;
7213
7214 MockRead data_reads[] = {
7215 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357216 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547217 MockRead("hello world"),
7218 MockRead(true, OK),
7219 };
7220
7221 StaticSocketDataProvider first_transaction(
7222 data_reads, arraysize(data_reads), NULL, 0);
7223 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7224
7225 SSLSocketDataProvider ssl(true, OK);
7226 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:207227 ssl.next_proto = "spdy/2.1";
[email protected]65041fa2010-05-21 06:56:537228 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:207229 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2ff8b312010-04-26 22:20:547230 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537231 // Make sure we use ssl for spdy here.
7232 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547233
[email protected]2bd93022010-07-17 00:58:447234 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137235 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547236
[email protected]2bd93022010-07-17 00:58:447237 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7238 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547239 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137240 CreateMockRead(*resp),
7241 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547242 MockRead(true, 0, 0),
7243 };
7244
[email protected]a1595312012-01-22 03:25:047245 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:547246 new DelayedSocketData(
7247 1, // wait for one write to finish before reading.
7248 spdy_reads, arraysize(spdy_reads),
7249 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047250 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:547251
[email protected]83039bb2011-12-09 18:43:557252 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:547253
7254 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7255
7256 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7257
[email protected]49639fa2011-12-20 23:22:417258 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547259 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417260 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547261
7262 const HttpResponseInfo* response = trans->GetResponseInfo();
7263 ASSERT_TRUE(response != NULL);
7264 ASSERT_TRUE(response->headers != NULL);
7265 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7266
7267 std::string response_data;
7268 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7269 EXPECT_EQ("hello world", response_data);
7270
7271 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387272 HostPortPair host_port_pair("www.google.com", 443);
7273 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547274 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317275 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287276 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:297277 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]02b0c342010-09-25 21:09:387278
7279 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7280 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287281 connection->Init(host_port_pair.ToString(),
7282 transport_params,
7283 LOWEST,
[email protected]6ecf2b92011-12-15 01:14:527284 callback.callback(),
[email protected]a42dbd142011-11-17 16:42:027285 session->GetTransportSocketPool(),
[email protected]02b0c342010-09-25 21:09:387286 BoundNetLog()));
[email protected]6ecf2b92011-12-15 01:14:527287 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]02b0c342010-09-25 21:09:387288
7289 SSLConfig ssl_config;
7290 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347291 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177292 SSLClientSocketContext context;
7293 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347294 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7295 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177296 NULL /* ssl_host_info */, context));
[email protected]83039bb2011-12-09 18:43:557297 EXPECT_EQ(ERR_IO_PENDING,
7298 ssl_connection->socket()->Connect(callback.callback()));
[email protected]02b0c342010-09-25 21:09:387299 EXPECT_EQ(OK, callback.WaitForResult());
7300
[email protected]9e1bdd32011-02-03 21:48:347301 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387302 true, OK));
7303
[email protected]2ff8b312010-04-26 22:20:547304 trans.reset(new HttpNetworkTransaction(session));
7305
[email protected]49639fa2011-12-20 23:22:417306 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547307 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417308 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547309
7310 response = trans->GetResponseInfo();
7311 ASSERT_TRUE(response != NULL);
7312 ASSERT_TRUE(response->headers != NULL);
7313 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537314 EXPECT_TRUE(response->was_fetched_via_spdy);
7315 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547316
7317 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7318 EXPECT_EQ("hello!", response_data);
7319
[email protected]5285d972011-10-18 18:56:347320 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387321 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427322}
7323
[email protected]044de0642010-06-17 10:42:157324// GenerateAuthToken is a mighty big test.
7325// It tests all permutation of GenerateAuthToken behavior:
7326// - Synchronous and Asynchronous completion.
7327// - OK or error on completion.
7328// - Direct connection, non-authenticating proxy, and authenticating proxy.
7329// - HTTP or HTTPS backend (to include proxy tunneling).
7330// - Non-authenticating and authenticating backend.
7331//
[email protected]fe3b7dc2012-02-03 19:52:097332// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:157333// problems generating an auth token for an authenticating proxy, we don't
7334// need to test all permutations of the backend server).
7335//
7336// The test proceeds by going over each of the configuration cases, and
7337// potentially running up to three rounds in each of the tests. The TestConfig
7338// specifies both the configuration for the test as well as the expectations
7339// for the results.
7340TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507341 static const char kServer[] = "http://www.example.com";
7342 static const char kSecureServer[] = "https://www.example.com";
7343 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157344 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7345
7346 enum AuthTiming {
7347 AUTH_NONE,
7348 AUTH_SYNC,
7349 AUTH_ASYNC,
7350 };
7351
7352 const MockWrite kGet(
7353 "GET / HTTP/1.1\r\n"
7354 "Host: www.example.com\r\n"
7355 "Connection: keep-alive\r\n\r\n");
7356 const MockWrite kGetProxy(
7357 "GET http://www.example.com/ HTTP/1.1\r\n"
7358 "Host: www.example.com\r\n"
7359 "Proxy-Connection: keep-alive\r\n\r\n");
7360 const MockWrite kGetAuth(
7361 "GET / HTTP/1.1\r\n"
7362 "Host: www.example.com\r\n"
7363 "Connection: keep-alive\r\n"
7364 "Authorization: auth_token\r\n\r\n");
7365 const MockWrite kGetProxyAuth(
7366 "GET http://www.example.com/ HTTP/1.1\r\n"
7367 "Host: www.example.com\r\n"
7368 "Proxy-Connection: keep-alive\r\n"
7369 "Proxy-Authorization: auth_token\r\n\r\n");
7370 const MockWrite kGetAuthThroughProxy(
7371 "GET http://www.example.com/ HTTP/1.1\r\n"
7372 "Host: www.example.com\r\n"
7373 "Proxy-Connection: keep-alive\r\n"
7374 "Authorization: auth_token\r\n\r\n");
7375 const MockWrite kGetAuthWithProxyAuth(
7376 "GET http://www.example.com/ HTTP/1.1\r\n"
7377 "Host: www.example.com\r\n"
7378 "Proxy-Connection: keep-alive\r\n"
7379 "Proxy-Authorization: auth_token\r\n"
7380 "Authorization: auth_token\r\n\r\n");
7381 const MockWrite kConnect(
7382 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7383 "Host: www.example.com\r\n"
7384 "Proxy-Connection: keep-alive\r\n\r\n");
7385 const MockWrite kConnectProxyAuth(
7386 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7387 "Host: www.example.com\r\n"
7388 "Proxy-Connection: keep-alive\r\n"
7389 "Proxy-Authorization: auth_token\r\n\r\n");
7390
7391 const MockRead kSuccess(
7392 "HTTP/1.1 200 OK\r\n"
7393 "Content-Type: text/html; charset=iso-8859-1\r\n"
7394 "Content-Length: 3\r\n\r\n"
7395 "Yes");
7396 const MockRead kFailure(
7397 "Should not be called.");
7398 const MockRead kServerChallenge(
7399 "HTTP/1.1 401 Unauthorized\r\n"
7400 "WWW-Authenticate: Mock realm=server\r\n"
7401 "Content-Type: text/html; charset=iso-8859-1\r\n"
7402 "Content-Length: 14\r\n\r\n"
7403 "Unauthorized\r\n");
7404 const MockRead kProxyChallenge(
7405 "HTTP/1.1 407 Unauthorized\r\n"
7406 "Proxy-Authenticate: Mock realm=proxy\r\n"
7407 "Proxy-Connection: close\r\n"
7408 "Content-Type: text/html; charset=iso-8859-1\r\n"
7409 "Content-Length: 14\r\n\r\n"
7410 "Unauthorized\r\n");
7411 const MockRead kProxyConnected(
7412 "HTTP/1.1 200 Connection Established\r\n\r\n");
7413
7414 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7415 // no constructors, but the C++ compiler on Windows warns about
7416 // unspecified data in compound literals. So, moved to using constructors,
7417 // and TestRound's created with the default constructor should not be used.
7418 struct TestRound {
7419 TestRound()
7420 : expected_rv(ERR_UNEXPECTED),
7421 extra_write(NULL),
7422 extra_read(NULL) {
7423 }
7424 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7425 int expected_rv_arg)
7426 : write(write_arg),
7427 read(read_arg),
7428 expected_rv(expected_rv_arg),
7429 extra_write(NULL),
7430 extra_read(NULL) {
7431 }
7432 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7433 int expected_rv_arg, const MockWrite* extra_write_arg,
7434 const MockWrite* extra_read_arg)
7435 : write(write_arg),
7436 read(read_arg),
7437 expected_rv(expected_rv_arg),
7438 extra_write(extra_write_arg),
7439 extra_read(extra_read_arg) {
7440 }
7441 MockWrite write;
7442 MockRead read;
7443 int expected_rv;
7444 const MockWrite* extra_write;
7445 const MockRead* extra_read;
7446 };
7447
7448 static const int kNoSSL = 500;
7449
7450 struct TestConfig {
7451 const char* proxy_url;
7452 AuthTiming proxy_auth_timing;
7453 int proxy_auth_rv;
7454 const char* server_url;
7455 AuthTiming server_auth_timing;
7456 int server_auth_rv;
7457 int num_auth_rounds;
7458 int first_ssl_round;
7459 TestRound rounds[3];
7460 } test_configs[] = {
7461 // Non-authenticating HTTP server with a direct connection.
7462 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7463 { TestRound(kGet, kSuccess, OK)}},
7464 // Authenticating HTTP server with a direct connection.
7465 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7466 { TestRound(kGet, kServerChallenge, OK),
7467 TestRound(kGetAuth, kSuccess, OK)}},
7468 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7469 { TestRound(kGet, kServerChallenge, OK),
7470 TestRound(kGetAuth, kFailure, kAuthErr)}},
7471 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7472 { TestRound(kGet, kServerChallenge, OK),
7473 TestRound(kGetAuth, kSuccess, OK)}},
7474 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7475 { TestRound(kGet, kServerChallenge, OK),
7476 TestRound(kGetAuth, kFailure, kAuthErr)}},
7477 // Non-authenticating HTTP server through a non-authenticating proxy.
7478 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7479 { TestRound(kGetProxy, kSuccess, OK)}},
7480 // Authenticating HTTP server through a non-authenticating proxy.
7481 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7482 { TestRound(kGetProxy, kServerChallenge, OK),
7483 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7484 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7485 { TestRound(kGetProxy, kServerChallenge, OK),
7486 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7487 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7488 { TestRound(kGetProxy, kServerChallenge, OK),
7489 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7490 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7491 { TestRound(kGetProxy, kServerChallenge, OK),
7492 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7493 // Non-authenticating HTTP server through an authenticating proxy.
7494 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7495 { TestRound(kGetProxy, kProxyChallenge, OK),
7496 TestRound(kGetProxyAuth, kSuccess, OK)}},
7497 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7498 { TestRound(kGetProxy, kProxyChallenge, OK),
7499 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7500 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7501 { TestRound(kGetProxy, kProxyChallenge, OK),
7502 TestRound(kGetProxyAuth, kSuccess, OK)}},
7503 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7504 { TestRound(kGetProxy, kProxyChallenge, OK),
7505 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7506 // Authenticating HTTP server through an authenticating proxy.
7507 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7508 { TestRound(kGetProxy, kProxyChallenge, OK),
7509 TestRound(kGetProxyAuth, kServerChallenge, OK),
7510 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7511 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7512 { TestRound(kGetProxy, kProxyChallenge, OK),
7513 TestRound(kGetProxyAuth, kServerChallenge, OK),
7514 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7515 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7516 { TestRound(kGetProxy, kProxyChallenge, OK),
7517 TestRound(kGetProxyAuth, kServerChallenge, OK),
7518 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7519 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7520 { TestRound(kGetProxy, kProxyChallenge, OK),
7521 TestRound(kGetProxyAuth, kServerChallenge, OK),
7522 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7523 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7524 { TestRound(kGetProxy, kProxyChallenge, OK),
7525 TestRound(kGetProxyAuth, kServerChallenge, OK),
7526 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7527 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7528 { TestRound(kGetProxy, kProxyChallenge, OK),
7529 TestRound(kGetProxyAuth, kServerChallenge, OK),
7530 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7531 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7532 { TestRound(kGetProxy, kProxyChallenge, OK),
7533 TestRound(kGetProxyAuth, kServerChallenge, OK),
7534 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7535 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7536 { TestRound(kGetProxy, kProxyChallenge, OK),
7537 TestRound(kGetProxyAuth, kServerChallenge, OK),
7538 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7539 // Non-authenticating HTTPS server with a direct connection.
7540 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7541 { TestRound(kGet, kSuccess, OK)}},
7542 // Authenticating HTTPS server with a direct connection.
7543 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7544 { TestRound(kGet, kServerChallenge, OK),
7545 TestRound(kGetAuth, kSuccess, OK)}},
7546 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7547 { TestRound(kGet, kServerChallenge, OK),
7548 TestRound(kGetAuth, kFailure, kAuthErr)}},
7549 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7550 { TestRound(kGet, kServerChallenge, OK),
7551 TestRound(kGetAuth, kSuccess, OK)}},
7552 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7553 { TestRound(kGet, kServerChallenge, OK),
7554 TestRound(kGetAuth, kFailure, kAuthErr)}},
7555 // Non-authenticating HTTPS server with a non-authenticating proxy.
7556 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7557 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7558 // Authenticating HTTPS server through a non-authenticating proxy.
7559 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7560 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7561 TestRound(kGetAuth, kSuccess, OK)}},
7562 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7563 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7564 TestRound(kGetAuth, kFailure, kAuthErr)}},
7565 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7566 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7567 TestRound(kGetAuth, kSuccess, OK)}},
7568 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7569 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7570 TestRound(kGetAuth, kFailure, kAuthErr)}},
7571 // Non-Authenticating HTTPS server through an authenticating proxy.
7572 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7573 { TestRound(kConnect, kProxyChallenge, OK),
7574 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7575 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7576 { TestRound(kConnect, kProxyChallenge, OK),
7577 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7578 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7579 { TestRound(kConnect, kProxyChallenge, OK),
7580 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7581 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7582 { TestRound(kConnect, kProxyChallenge, OK),
7583 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7584 // Authenticating HTTPS server through an authenticating proxy.
7585 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7586 { TestRound(kConnect, kProxyChallenge, OK),
7587 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7588 &kGet, &kServerChallenge),
7589 TestRound(kGetAuth, kSuccess, OK)}},
7590 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7591 { TestRound(kConnect, kProxyChallenge, OK),
7592 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7593 &kGet, &kServerChallenge),
7594 TestRound(kGetAuth, kFailure, kAuthErr)}},
7595 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7596 { TestRound(kConnect, kProxyChallenge, OK),
7597 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7598 &kGet, &kServerChallenge),
7599 TestRound(kGetAuth, kSuccess, OK)}},
7600 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7601 { TestRound(kConnect, kProxyChallenge, OK),
7602 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7603 &kGet, &kServerChallenge),
7604 TestRound(kGetAuth, kFailure, kAuthErr)}},
7605 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7606 { TestRound(kConnect, kProxyChallenge, OK),
7607 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7608 &kGet, &kServerChallenge),
7609 TestRound(kGetAuth, kSuccess, OK)}},
7610 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7611 { TestRound(kConnect, kProxyChallenge, OK),
7612 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7613 &kGet, &kServerChallenge),
7614 TestRound(kGetAuth, kFailure, kAuthErr)}},
7615 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7616 { TestRound(kConnect, kProxyChallenge, OK),
7617 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7618 &kGet, &kServerChallenge),
7619 TestRound(kGetAuth, kSuccess, OK)}},
7620 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7621 { TestRound(kConnect, kProxyChallenge, OK),
7622 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7623 &kGet, &kServerChallenge),
7624 TestRound(kGetAuth, kFailure, kAuthErr)}},
7625 };
7626
7627 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157628 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087629 HttpAuthHandlerMock::Factory* auth_factory(
7630 new HttpAuthHandlerMock::Factory());
7631 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157632 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267633
7634 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157635 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087636 for (int n = 0; n < 2; n++) {
7637 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7638 std::string auth_challenge = "Mock realm=proxy";
7639 GURL origin(test_config.proxy_url);
7640 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7641 auth_challenge.end());
7642 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7643 origin, BoundNetLog());
7644 auth_handler->SetGenerateExpectation(
7645 test_config.proxy_auth_timing == AUTH_ASYNC,
7646 test_config.proxy_auth_rv);
7647 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7648 }
[email protected]044de0642010-06-17 10:42:157649 }
7650 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007651 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157652 std::string auth_challenge = "Mock realm=server";
7653 GURL origin(test_config.server_url);
7654 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7655 auth_challenge.end());
7656 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7657 origin, BoundNetLog());
7658 auth_handler->SetGenerateExpectation(
7659 test_config.server_auth_timing == AUTH_ASYNC,
7660 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087661 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157662 }
7663 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127664 session_deps.proxy_service.reset(
7665 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157666 } else {
[email protected]6104ea5d2011-04-27 21:37:127667 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157668 }
7669
7670 HttpRequestInfo request;
7671 request.method = "GET";
7672 request.url = GURL(test_config.server_url);
7673 request.load_flags = 0;
7674
[email protected]0b0bf032010-09-21 18:08:507675 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7676 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157677
7678 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7679 const TestRound& read_write_round = test_config.rounds[round];
7680
7681 // Set up expected reads and writes.
7682 MockRead reads[2];
7683 reads[0] = read_write_round.read;
7684 size_t length_reads = 1;
7685 if (read_write_round.extra_read) {
7686 reads[1] = *read_write_round.extra_read;
7687 length_reads = 2;
7688 }
7689
7690 MockWrite writes[2];
7691 writes[0] = read_write_round.write;
7692 size_t length_writes = 1;
7693 if (read_write_round.extra_write) {
7694 writes[1] = *read_write_round.extra_write;
7695 length_writes = 2;
7696 }
7697 StaticSocketDataProvider data_provider(
7698 reads, length_reads, writes, length_writes);
7699 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7700
7701 // Add an SSL sequence if necessary.
7702 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7703 if (round >= test_config.first_ssl_round)
7704 session_deps.socket_factory.AddSSLSocketDataProvider(
7705 &ssl_socket_data_provider);
7706
7707 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:417708 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:157709 int rv;
7710 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:417711 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:157712 } else {
[email protected]49639fa2011-12-20 23:22:417713 rv = trans.RestartWithAuth(
7714 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:157715 }
7716 if (rv == ERR_IO_PENDING)
7717 rv = callback.WaitForResult();
7718
7719 // Compare results with expected data.
7720 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507721 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157722 if (read_write_round.expected_rv == OK) {
[email protected]fe2255a2011-09-20 19:37:507723 ASSERT_TRUE(response != NULL);
[email protected]044de0642010-06-17 10:42:157724 } else {
7725 EXPECT_TRUE(response == NULL);
7726 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7727 continue;
7728 }
7729 if (round + 1 < test_config.num_auth_rounds) {
7730 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7731 } else {
7732 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7733 }
7734 }
[email protected]e5ae96a2010-04-14 20:12:457735 }
7736}
7737
[email protected]c871bce92010-07-15 21:51:147738TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7739 // Do multi-round authentication and make sure it works correctly.
7740 SessionDependencies session_deps;
7741 HttpAuthHandlerMock::Factory* auth_factory(
7742 new HttpAuthHandlerMock::Factory());
7743 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127744 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147745 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7746 session_deps.host_resolver->set_synchronous_mode(true);
7747
7748 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7749 auth_handler->set_connection_based(true);
7750 std::string auth_challenge = "Mock realm=server";
7751 GURL origin("http://www.example.com");
7752 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7753 auth_challenge.end());
7754 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7755 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087756 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147757
[email protected]c871bce92010-07-15 21:51:147758 int rv = OK;
7759 const HttpResponseInfo* response = NULL;
7760 HttpRequestInfo request;
7761 request.method = "GET";
7762 request.url = origin;
7763 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277764
7765 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107766
7767 // Use a TCP Socket Pool with only one connection per group. This is used
7768 // to validate that the TCP socket is not released to the pool between
7769 // each round of multi-round authentication.
7770 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287771 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7772 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107773 50, // Max sockets for pool
7774 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287775 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107776 session_deps.host_resolver.get(),
7777 &session_deps.socket_factory,
7778 session_deps.net_log);
[email protected]a42dbd142011-11-17 16:42:027779 MockClientSocketPoolManager* mock_pool_manager =
7780 new MockClientSocketPoolManager;
7781 mock_pool_manager->SetTransportSocketPool(transport_pool);
7782 session_peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]7ef4cbbb2011-02-06 11:19:107783
[email protected]cb9bf6ca2011-01-28 13:15:277784 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417785 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:147786
7787 const MockWrite kGet(
7788 "GET / HTTP/1.1\r\n"
7789 "Host: www.example.com\r\n"
7790 "Connection: keep-alive\r\n\r\n");
7791 const MockWrite kGetAuth(
7792 "GET / HTTP/1.1\r\n"
7793 "Host: www.example.com\r\n"
7794 "Connection: keep-alive\r\n"
7795 "Authorization: auth_token\r\n\r\n");
7796
7797 const MockRead kServerChallenge(
7798 "HTTP/1.1 401 Unauthorized\r\n"
7799 "WWW-Authenticate: Mock realm=server\r\n"
7800 "Content-Type: text/html; charset=iso-8859-1\r\n"
7801 "Content-Length: 14\r\n\r\n"
7802 "Unauthorized\r\n");
7803 const MockRead kSuccess(
7804 "HTTP/1.1 200 OK\r\n"
7805 "Content-Type: text/html; charset=iso-8859-1\r\n"
7806 "Content-Length: 3\r\n\r\n"
7807 "Yes");
7808
7809 MockWrite writes[] = {
7810 // First round
7811 kGet,
7812 // Second round
7813 kGetAuth,
7814 // Third round
7815 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307816 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107817 kGetAuth,
7818 // Competing request
7819 kGet,
[email protected]c871bce92010-07-15 21:51:147820 };
7821 MockRead reads[] = {
7822 // First round
7823 kServerChallenge,
7824 // Second round
7825 kServerChallenge,
7826 // Third round
[email protected]eca50e122010-09-11 14:03:307827 kServerChallenge,
7828 // Fourth round
[email protected]c871bce92010-07-15 21:51:147829 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107830 // Competing response
7831 kSuccess,
[email protected]c871bce92010-07-15 21:51:147832 };
7833 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7834 writes, arraysize(writes));
7835 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7836
[email protected]7ef4cbbb2011-02-06 11:19:107837 const char* const kSocketGroup = "www.example.com:80";
7838
7839 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147840 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417841 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:147842 if (rv == ERR_IO_PENDING)
7843 rv = callback.WaitForResult();
7844 EXPECT_EQ(OK, rv);
7845 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507846 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147847 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287848 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147849
[email protected]7ef4cbbb2011-02-06 11:19:107850 // In between rounds, another request comes in for the same domain.
7851 // It should not be able to grab the TCP socket that trans has already
7852 // claimed.
7853 scoped_ptr<HttpTransaction> trans_compete(
7854 new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417855 TestCompletionCallback callback_compete;
7856 rv = trans_compete->Start(
7857 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:107858 EXPECT_EQ(ERR_IO_PENDING, rv);
7859 // callback_compete.WaitForResult at this point would stall forever,
7860 // since the HttpNetworkTransaction does not release the request back to
7861 // the pool until after authentication completes.
7862
7863 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147864 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417865 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:147866 if (rv == ERR_IO_PENDING)
7867 rv = callback.WaitForResult();
7868 EXPECT_EQ(OK, rv);
7869 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507870 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147871 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287872 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147873
[email protected]7ef4cbbb2011-02-06 11:19:107874 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147875 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417876 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:147877 if (rv == ERR_IO_PENDING)
7878 rv = callback.WaitForResult();
7879 EXPECT_EQ(OK, rv);
7880 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507881 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147882 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287883 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307884
[email protected]7ef4cbbb2011-02-06 11:19:107885 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307886 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417887 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:307888 if (rv == ERR_IO_PENDING)
7889 rv = callback.WaitForResult();
7890 EXPECT_EQ(OK, rv);
7891 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507892 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:307893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287894 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107895
7896 // Read the body since the fourth round was successful. This will also
7897 // release the socket back to the pool.
7898 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]49639fa2011-12-20 23:22:417899 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107900 if (rv == ERR_IO_PENDING)
7901 rv = callback.WaitForResult();
7902 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:417903 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107904 EXPECT_EQ(0, rv);
7905 // There are still 0 idle sockets, since the trans_compete transaction
7906 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287907 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107908
7909 // The competing request can now finish. Wait for the headers and then
7910 // read the body.
7911 rv = callback_compete.WaitForResult();
7912 EXPECT_EQ(OK, rv);
[email protected]49639fa2011-12-20 23:22:417913 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107914 if (rv == ERR_IO_PENDING)
7915 rv = callback.WaitForResult();
7916 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:417917 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:107918 EXPECT_EQ(0, rv);
7919
7920 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287921 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147922}
7923
[email protected]aeaca1f2010-04-20 22:05:217924class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7925 public:
[email protected]06650c52010-06-03 00:49:177926 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217927 : fail_all_(fail_all) {
7928 }
7929
7930 virtual MockRead GetNextRead() {
7931 if (fail_all_)
7932 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7933
7934 return MockRead(false /* async */,
7935 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7936 }
7937
7938 virtual MockWriteResult OnWrite(const std::string& data) {
7939 return MockWriteResult(false /* async */, data.size());
7940 }
7941
7942 void Reset() {
7943 }
7944
7945 private:
7946 const bool fail_all_;
7947};
7948
7949// Test that we restart a connection when we see a decompression failure from
7950// the peer during the handshake. (In the real world we'll restart with SSLv3
7951// and we won't offer DEFLATE in that case.)
7952TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7953 HttpRequestInfo request;
7954 request.method = "GET";
7955 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7956 request.load_flags = 0;
7957
7958 SessionDependencies session_deps;
7959 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7960 false /* fail all reads */);
7961 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7962 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117963 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217964 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7965 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7966 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7967 session_deps.socket_factory.AddSSLSocketDataProvider(
7968 &ssl_socket_data_provider1);
7969 session_deps.socket_factory.AddSSLSocketDataProvider(
7970 &ssl_socket_data_provider2);
7971
[email protected]e60e47a2010-07-14 03:37:187972 // Work around http://crbug.com/37454
7973 StaticSocketDataProvider bug37454_connection;
7974 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7975 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7976
[email protected]aeaca1f2010-04-20 22:05:217977 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7978 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417979 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:217980
[email protected]49639fa2011-12-20 23:22:417981 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217982 EXPECT_EQ(ERR_IO_PENDING, rv);
7983 EXPECT_EQ(OK, callback.WaitForResult());
7984
7985 const HttpResponseInfo* response = trans->GetResponseInfo();
7986 ASSERT_TRUE(response != NULL);
7987 ASSERT_TRUE(response->headers != NULL);
7988 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7989
7990 std::string response_data;
7991 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7992 EXPECT_EQ("ok.", response_data);
7993}
7994
7995// Test that we restart a connection if we get a decompression failure from the
7996// peer while reading the first bytes from the connection. This occurs when the
7997// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7998// in the handshake.
7999TEST_F(HttpNetworkTransactionTest,
8000 RestartAfterTLSDecompressionFailureWithFalseStart) {
8001 HttpRequestInfo request;
8002 request.method = "GET";
8003 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
8004 request.load_flags = 0;
8005
8006 SessionDependencies session_deps;
8007 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8008 true /* fail all reads */);
8009 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8010 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
8011 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
8012 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8013 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8014 session_deps.socket_factory.AddSSLSocketDataProvider(
8015 &ssl_socket_data_provider1);
8016 session_deps.socket_factory.AddSSLSocketDataProvider(
8017 &ssl_socket_data_provider2);
8018
8019 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8020 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418021 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218022
[email protected]49639fa2011-12-20 23:22:418023 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218024 EXPECT_EQ(ERR_IO_PENDING, rv);
8025 EXPECT_EQ(OK, callback.WaitForResult());
8026
8027 const HttpResponseInfo* response = trans->GetResponseInfo();
8028 ASSERT_TRUE(response != NULL);
8029 ASSERT_TRUE(response->headers != NULL);
8030 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8031
8032 std::string response_data;
8033 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8034 EXPECT_EQ("ok.", response_data);
8035}
8036
[email protected]65041fa2010-05-21 06:56:538037// This tests the case that a request is issued via http instead of spdy after
8038// npn is negotiated.
8039TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:388040 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348041 HttpStreamFactory::set_next_protos(
8042 MakeNextProtos("http/1.1", "http1.1", NULL));
[email protected]65041fa2010-05-21 06:56:538043 SessionDependencies session_deps;
8044 HttpRequestInfo request;
8045 request.method = "GET";
8046 request.url = GURL("https://www.google.com/");
8047 request.load_flags = 0;
8048
8049 MockWrite data_writes[] = {
8050 MockWrite("GET / HTTP/1.1\r\n"
8051 "Host: www.google.com\r\n"
8052 "Connection: keep-alive\r\n\r\n"),
8053 };
8054
8055 MockRead data_reads[] = {
8056 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:358057 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:538058 MockRead("hello world"),
8059 MockRead(false, OK),
8060 };
8061
8062 SSLSocketDataProvider ssl(true, OK);
8063 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8064 ssl.next_proto = "http/1.1";
[email protected]c30bcce2011-12-20 17:50:518065 ssl.protocol_negotiated = SSLClientSocket::kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:538066
8067 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8068
8069 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8070 data_writes, arraysize(data_writes));
8071 session_deps.socket_factory.AddSocketDataProvider(&data);
8072
[email protected]49639fa2011-12-20 23:22:418073 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:538074
8075 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8076 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8077
[email protected]49639fa2011-12-20 23:22:418078 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:538079
8080 EXPECT_EQ(ERR_IO_PENDING, rv);
8081 EXPECT_EQ(OK, callback.WaitForResult());
8082
8083 const HttpResponseInfo* response = trans->GetResponseInfo();
8084 ASSERT_TRUE(response != NULL);
8085 ASSERT_TRUE(response->headers != NULL);
8086 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8087
8088 std::string response_data;
8089 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8090 EXPECT_EQ("hello world", response_data);
8091
8092 EXPECT_FALSE(response->was_fetched_via_spdy);
8093 EXPECT_TRUE(response->was_npn_negotiated);
8094
[email protected]5285d972011-10-18 18:56:348095 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388096 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:538097}
[email protected]26ef6582010-06-24 02:30:478098
8099TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8100 // Simulate the SSL handshake completing with an NPN negotiation
8101 // followed by an immediate server closing of the socket.
8102 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:388103 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348104 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]26ef6582010-06-24 02:30:478105 SessionDependencies session_deps;
8106
8107 HttpRequestInfo request;
8108 request.method = "GET";
8109 request.url = GURL("https://www.google.com/");
8110 request.load_flags = 0;
8111
8112 SSLSocketDataProvider ssl(true, OK);
8113 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208114 ssl.next_proto = "spdy/2.1";
[email protected]26ef6582010-06-24 02:30:478115 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208116 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]26ef6582010-06-24 02:30:478117 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8118
[email protected]2bd93022010-07-17 00:58:448119 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:138120 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:478121
8122 MockRead spdy_reads[] = {
8123 MockRead(false, 0, 0) // Not async - return 0 immediately.
8124 };
8125
[email protected]a1595312012-01-22 03:25:048126 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]26ef6582010-06-24 02:30:478127 new DelayedSocketData(
8128 0, // don't wait in this case, immediate hangup.
8129 spdy_reads, arraysize(spdy_reads),
8130 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048131 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]26ef6582010-06-24 02:30:478132
[email protected]49639fa2011-12-20 23:22:418133 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:478134
8135 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8136 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8137
[email protected]49639fa2011-12-20 23:22:418138 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:478139 EXPECT_EQ(ERR_IO_PENDING, rv);
8140 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8141
[email protected]5285d972011-10-18 18:56:348142 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388143 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:478144}
[email protected]65d34382010-07-01 18:12:268145
[email protected]f45c1ee2010-08-03 00:54:308146TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8147 // This test ensures that the URL passed into the proxy is upgraded
8148 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:388149 HttpStreamFactory::set_use_alternate_protocols(true);
8150 HttpStreamFactory::set_next_protos(
[email protected]42baef7a2011-12-10 04:52:108151 MakeNextProtos(
8152 "http/1.1", "http1.1", "spdy/2.1", "spdy/2", "spdy", NULL));
[email protected]f45c1ee2010-08-03 00:54:308153
[email protected]81cdfcd2010-10-16 00:49:008154 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:308155 HttpAuthHandlerMock::Factory* auth_factory =
8156 new HttpAuthHandlerMock::Factory();
[email protected]767257802011-12-14 17:33:188157 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
8158 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:308159 auth_factory->set_do_init_from_challenge(true);
8160 session_deps.http_auth_handler_factory.reset(auth_factory);
8161
8162 HttpRequestInfo request;
8163 request.method = "GET";
8164 request.url = GURL("http://www.google.com");
8165 request.load_flags = 0;
8166
8167 // First round goes unauthenticated through the proxy.
8168 MockWrite data_writes_1[] = {
8169 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8170 "Host: www.google.com\r\n"
8171 "Proxy-Connection: keep-alive\r\n"
8172 "\r\n"),
8173 };
8174 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:598175 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:308176 MockRead("HTTP/1.1 200 OK\r\n"
[email protected]8d2f7012012-02-16 00:08:048177 "Alternate-Protocol: 443:npn-spdy/2.1\r\n"
[email protected]f45c1ee2010-08-03 00:54:308178 "Proxy-Connection: close\r\n"
8179 "\r\n"),
8180 };
8181 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8182 data_writes_1, arraysize(data_writes_1));
8183
8184 // Second round tries to tunnel to www.google.com due to the
8185 // Alternate-Protocol announcement in the first round. It fails due
8186 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:598187 // After the failure, a tunnel is established to www.google.com using
8188 // Proxy-Authorization headers. There is then a SPDY request round.
8189 //
[email protected]fe3b7dc2012-02-03 19:52:098190 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8191 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8192 // does a Disconnect and Connect on the same socket, rather than trying
8193 // to obtain a new one.
8194 //
[email protected]394816e92010-08-03 07:38:598195 // NOTE: Originally, the proxy response to the second CONNECT request
8196 // simply returned another 407 so the unit test could skip the SSL connection
8197 // establishment and SPDY framing issues. Alas, the
8198 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308199 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598200
[email protected]f45c1ee2010-08-03 00:54:308201 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8202 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8203 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8204
[email protected]394816e92010-08-03 07:38:598205 MockWrite data_writes_2[] = {
8206 // First connection attempt without Proxy-Authorization.
8207 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8208 "Host: www.google.com\r\n"
8209 "Proxy-Connection: keep-alive\r\n"
8210 "\r\n"),
8211
8212 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308213 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8214 "Host: www.google.com\r\n"
8215 "Proxy-Connection: keep-alive\r\n"
8216 "Proxy-Authorization: auth_token\r\n"
8217 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308218
[email protected]394816e92010-08-03 07:38:598219 // SPDY request
8220 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308221 };
[email protected]394816e92010-08-03 07:38:598222 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8223 "Proxy-Authenticate: Mock\r\n"
8224 "Proxy-Connection: close\r\n"
8225 "\r\n");
8226 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8227 MockRead data_reads_2[] = {
8228 // First connection attempt fails
8229 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8230 MockRead(true, kRejectConnectResponse,
8231 arraysize(kRejectConnectResponse) - 1, 1),
8232
8233 // Second connection attempt passes
8234 MockRead(true, kAcceptConnectResponse,
[email protected]fe3b7dc2012-02-03 19:52:098235 arraysize(kAcceptConnectResponse) -1, 4),
[email protected]394816e92010-08-03 07:38:598236
8237 // SPDY response
[email protected]fe3b7dc2012-02-03 19:52:098238 CreateMockRead(*resp.get(), 6),
8239 CreateMockRead(*data.get(), 6),
8240 MockRead(true, 0, 0, 6),
[email protected]394816e92010-08-03 07:38:598241 };
[email protected]a1595312012-01-22 03:25:048242 scoped_ptr<OrderedSocketData> data_2(
[email protected]394816e92010-08-03 07:38:598243 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8244 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308245
8246 SSLSocketDataProvider ssl(true, OK);
8247 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208248 ssl.next_proto = "spdy/2.1";
[email protected]f45c1ee2010-08-03 00:54:308249 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208250 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]f45c1ee2010-08-03 00:54:308251
[email protected]2d6728692011-03-12 01:39:558252 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8253 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8254 NULL, 0, NULL, 0);
8255 hanging_non_alternate_protocol_socket.set_connect_data(
8256 never_finishing_connect);
8257
[email protected]f45c1ee2010-08-03 00:54:308258 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598259 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308260 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558261 session_deps.socket_factory.AddSocketDataProvider(
8262 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308263 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8264
8265 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:418266 TestCompletionCallback callback_1;
[email protected]f45c1ee2010-08-03 00:54:308267 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418268 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308269 EXPECT_EQ(ERR_IO_PENDING, rv);
8270 EXPECT_EQ(OK, callback_1.WaitForResult());
8271
8272 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:418273 TestCompletionCallback callback_2;
[email protected]f45c1ee2010-08-03 00:54:308274 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418275 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308276 EXPECT_EQ(ERR_IO_PENDING, rv);
8277 EXPECT_EQ(OK, callback_2.WaitForResult());
8278 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508279 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:308280 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8281
8282 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:418283 TestCompletionCallback callback_3;
8284 rv = trans_2->RestartWithAuth(
8285 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:308286 EXPECT_EQ(ERR_IO_PENDING, rv);
8287 EXPECT_EQ(OK, callback_3.WaitForResult());
8288
8289 // After all that work, these two lines (or actually, just the scheme) are
8290 // what this test is all about. Make sure it happens correctly.
[email protected]767257802011-12-14 17:33:188291 const GURL& request_url = auth_handler->request_url();
[email protected]f45c1ee2010-08-03 00:54:308292 EXPECT_EQ("https", request_url.scheme());
8293 EXPECT_EQ("www.google.com", request_url.host());
8294
[email protected]5285d972011-10-18 18:56:348295 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388296 HttpStreamFactory::set_use_alternate_protocols(false);
8297}
8298
8299// Test that if we cancel the transaction as the connection is completing, that
8300// everything tears down correctly.
8301TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8302 // Setup everything about the connection to complete synchronously, so that
8303 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8304 // for is the callback from the HttpStreamRequest.
8305 // Then cancel the transaction.
8306 // Verify that we don't crash.
8307 MockConnect mock_connect(false, OK);
8308 MockRead data_reads[] = {
8309 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8310 MockRead(false, "hello world"),
8311 MockRead(false, OK),
8312 };
8313
[email protected]8e6441ca2010-08-19 05:56:388314 HttpRequestInfo request;
8315 request.method = "GET";
8316 request.url = GURL("http://www.google.com/");
8317 request.load_flags = 0;
8318
[email protected]cb9bf6ca2011-01-28 13:15:278319 SessionDependencies session_deps;
8320 session_deps.host_resolver->set_synchronous_mode(true);
8321 scoped_ptr<HttpTransaction> trans(
8322 new HttpNetworkTransaction(CreateSession(&session_deps)));
8323
[email protected]8e6441ca2010-08-19 05:56:388324 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8325 data.set_connect_data(mock_connect);
8326 session_deps.socket_factory.AddSocketDataProvider(&data);
8327
[email protected]49639fa2011-12-20 23:22:418328 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:388329
8330 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]49639fa2011-12-20 23:22:418331 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:388332 EXPECT_EQ(ERR_IO_PENDING, rv);
8333 trans.reset(); // Cancel the transaction here.
8334
8335 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308336}
8337
[email protected]76a505b2010-08-25 06:23:008338// Test a basic GET request through a proxy.
8339TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008340 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008341 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8342 session_deps.net_log = log.bound().net_log();
8343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8344
[email protected]76a505b2010-08-25 06:23:008345 HttpRequestInfo request;
8346 request.method = "GET";
8347 request.url = GURL("http://www.google.com/");
8348
8349 MockWrite data_writes1[] = {
8350 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8351 "Host: www.google.com\r\n"
8352 "Proxy-Connection: keep-alive\r\n\r\n"),
8353 };
8354
8355 MockRead data_reads1[] = {
8356 MockRead("HTTP/1.1 200 OK\r\n"),
8357 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8358 MockRead("Content-Length: 100\r\n\r\n"),
8359 MockRead(false, OK),
8360 };
8361
8362 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8363 data_writes1, arraysize(data_writes1));
8364 session_deps.socket_factory.AddSocketDataProvider(&data1);
8365
[email protected]49639fa2011-12-20 23:22:418366 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008367
[email protected]0b0bf032010-09-21 18:08:508368 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8369
[email protected]49639fa2011-12-20 23:22:418370 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008371 EXPECT_EQ(ERR_IO_PENDING, rv);
8372
8373 rv = callback1.WaitForResult();
8374 EXPECT_EQ(OK, rv);
8375
8376 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508377 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008378
8379 EXPECT_TRUE(response->headers->IsKeepAlive());
8380 EXPECT_EQ(200, response->headers->response_code());
8381 EXPECT_EQ(100, response->headers->GetContentLength());
8382 EXPECT_TRUE(response->was_fetched_via_proxy);
8383 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8384}
8385
8386// Test a basic HTTPS GET request through a proxy.
8387TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008388 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008389 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8390 session_deps.net_log = log.bound().net_log();
8391 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8392
[email protected]76a505b2010-08-25 06:23:008393 HttpRequestInfo request;
8394 request.method = "GET";
8395 request.url = GURL("https://www.google.com/");
8396
8397 // Since we have proxy, should try to establish tunnel.
8398 MockWrite data_writes1[] = {
8399 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8400 "Host: www.google.com\r\n"
8401 "Proxy-Connection: keep-alive\r\n\r\n"),
8402
8403 MockWrite("GET / HTTP/1.1\r\n"
8404 "Host: www.google.com\r\n"
8405 "Connection: keep-alive\r\n\r\n"),
8406 };
8407
8408 MockRead data_reads1[] = {
8409 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8410
8411 MockRead("HTTP/1.1 200 OK\r\n"),
8412 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8413 MockRead("Content-Length: 100\r\n\r\n"),
8414 MockRead(false, OK),
8415 };
8416
8417 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8418 data_writes1, arraysize(data_writes1));
8419 session_deps.socket_factory.AddSocketDataProvider(&data1);
8420 SSLSocketDataProvider ssl(true, OK);
8421 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8422
[email protected]49639fa2011-12-20 23:22:418423 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008424
[email protected]0b0bf032010-09-21 18:08:508425 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8426
[email protected]49639fa2011-12-20 23:22:418427 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008428 EXPECT_EQ(ERR_IO_PENDING, rv);
8429
8430 rv = callback1.WaitForResult();
8431 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408432 net::CapturingNetLog::EntryList entries;
8433 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008434 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408435 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008436 NetLog::PHASE_NONE);
8437 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408438 entries, pos,
[email protected]76a505b2010-08-25 06:23:008439 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8440 NetLog::PHASE_NONE);
8441
8442 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508443 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008444
8445 EXPECT_TRUE(response->headers->IsKeepAlive());
8446 EXPECT_EQ(200, response->headers->response_code());
8447 EXPECT_EQ(100, response->headers->GetContentLength());
8448 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8449 EXPECT_TRUE(response->was_fetched_via_proxy);
8450}
8451
8452// Test a basic HTTPS GET request through a proxy, but the server hangs up
8453// while establishing the tunnel.
8454TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008455 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008456 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8457 session_deps.net_log = log.bound().net_log();
8458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8459
[email protected]76a505b2010-08-25 06:23:008460 HttpRequestInfo request;
8461 request.method = "GET";
8462 request.url = GURL("https://www.google.com/");
8463
8464 // Since we have proxy, should try to establish tunnel.
8465 MockWrite data_writes1[] = {
8466 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8467 "Host: www.google.com\r\n"
8468 "Proxy-Connection: keep-alive\r\n\r\n"),
8469
8470 MockWrite("GET / HTTP/1.1\r\n"
8471 "Host: www.google.com\r\n"
8472 "Connection: keep-alive\r\n\r\n"),
8473 };
8474
8475 MockRead data_reads1[] = {
8476 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8477 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8478 MockRead(true, 0, 0), // EOF
8479 };
8480
8481 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8482 data_writes1, arraysize(data_writes1));
8483 session_deps.socket_factory.AddSocketDataProvider(&data1);
8484 SSLSocketDataProvider ssl(true, OK);
8485 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8486
[email protected]49639fa2011-12-20 23:22:418487 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008488
[email protected]0b0bf032010-09-21 18:08:508489 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8490
[email protected]49639fa2011-12-20 23:22:418491 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008492 EXPECT_EQ(ERR_IO_PENDING, rv);
8493
8494 rv = callback1.WaitForResult();
8495 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408496 net::CapturingNetLog::EntryList entries;
8497 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008498 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408499 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008500 NetLog::PHASE_NONE);
8501 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408502 entries, pos,
[email protected]76a505b2010-08-25 06:23:008503 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8504 NetLog::PHASE_NONE);
8505}
8506
[email protected]749eefa82010-09-13 22:14:038507// Test for crbug.com/55424.
8508TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8509 SessionDependencies session_deps;
8510
8511 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8512 "https://www.google.com", false, 1, LOWEST));
8513 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8514
8515 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8516 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8517 MockRead spdy_reads[] = {
8518 CreateMockRead(*resp),
8519 CreateMockRead(*data),
8520 MockRead(true, 0, 0),
8521 };
8522
[email protected]a1595312012-01-22 03:25:048523 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]749eefa82010-09-13 22:14:038524 new DelayedSocketData(
8525 1, // wait for one write to finish before reading.
8526 spdy_reads, arraysize(spdy_reads),
8527 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048528 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]749eefa82010-09-13 22:14:038529
8530 SSLSocketDataProvider ssl(true, OK);
8531 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208532 ssl.next_proto = "spdy/2.1";
[email protected]749eefa82010-09-13 22:14:038533 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208534 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]749eefa82010-09-13 22:14:038535 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8536
8537 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8538
8539 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388540 HostPortPair host_port_pair("www.google.com", 443);
8541 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038542 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318543 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288544 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:298545 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]6ecf2b92011-12-15 01:14:528546 TestCompletionCallback callback;
[email protected]02b0c342010-09-25 21:09:388547
8548 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8549 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288550 connection->Init(host_port_pair.ToString(), transport_params,
[email protected]6ecf2b92011-12-15 01:14:528551 LOWEST, callback.callback(),
[email protected]a42dbd142011-11-17 16:42:028552 session->GetTransportSocketPool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388553 EXPECT_EQ(OK, callback.WaitForResult());
8554 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038555
8556 HttpRequestInfo request;
8557 request.method = "GET";
8558 request.url = GURL("https://www.google.com/");
8559 request.load_flags = 0;
8560
8561 // This is the important line that marks this as a preconnect.
8562 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8563
8564 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8565
[email protected]49639fa2011-12-20 23:22:418566 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:038567 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:418568 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:038569}
8570
[email protected]73b8dd222010-11-11 19:55:248571// Given a net error, cause that error to be returned from the first Write()
8572// call and verify that the HttpTransaction fails with that error.
8573static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278574 net::HttpRequestInfo request_info;
8575 request_info.url = GURL("https://www.example.com/");
8576 request_info.method = "GET";
8577 request_info.load_flags = net::LOAD_NORMAL;
8578
[email protected]73b8dd222010-11-11 19:55:248579 SessionDependencies session_deps;
8580
8581 SSLSocketDataProvider ssl_data(async, OK);
8582 net::MockWrite data_writes[] = {
8583 net::MockWrite(async, error),
8584 };
8585 net::StaticSocketDataProvider data(NULL, 0,
8586 data_writes, arraysize(data_writes));
8587 session_deps.socket_factory.AddSocketDataProvider(&data);
8588 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8589
8590 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8591 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8592
[email protected]49639fa2011-12-20 23:22:418593 TestCompletionCallback callback;
8594 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]73b8dd222010-11-11 19:55:248595 if (rv == net::ERR_IO_PENDING)
8596 rv = callback.WaitForResult();
8597 ASSERT_EQ(error, rv);
8598}
8599
8600TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8601 // Just check a grab bag of cert errors.
8602 static const int kErrors[] = {
8603 ERR_CERT_COMMON_NAME_INVALID,
8604 ERR_CERT_AUTHORITY_INVALID,
8605 ERR_CERT_DATE_INVALID,
8606 };
8607 for (size_t i = 0; i < arraysize(kErrors); i++) {
8608 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8609 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8610 }
8611}
8612
[email protected]bd0b6772011-01-11 19:59:308613// Ensure that a client certificate is removed from the SSL client auth
8614// cache when:
8615// 1) No proxy is involved.
8616// 2) TLS False Start is disabled.
8617// 3) The initial TLS handshake requests a client certificate.
8618// 4) The client supplies an invalid/unacceptable certificate.
8619TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278620 net::HttpRequestInfo request_info;
8621 request_info.url = GURL("https://www.example.com/");
8622 request_info.method = "GET";
8623 request_info.load_flags = net::LOAD_NORMAL;
8624
[email protected]bd0b6772011-01-11 19:59:308625 SessionDependencies session_deps;
8626
8627 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8628 cert_request->host_and_port = "www.example.com:443";
8629
8630 // [ssl_]data1 contains the data for the first SSL handshake. When a
8631 // CertificateRequest is received for the first time, the handshake will
8632 // be aborted to allow the caller to provide a certificate.
8633 SSLSocketDataProvider ssl_data1(true /* async */,
8634 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8635 ssl_data1.cert_request_info = cert_request.get();
8636 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8637 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8638 session_deps.socket_factory.AddSocketDataProvider(&data1);
8639
8640 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8641 // False Start is not being used, the result of the SSL handshake will be
8642 // returned as part of the SSLClientSocket::Connect() call. This test
8643 // matches the result of a server sending a handshake_failure alert,
8644 // rather than a Finished message, because it requires a client
8645 // certificate and none was supplied.
8646 SSLSocketDataProvider ssl_data2(true /* async */,
8647 net::ERR_SSL_PROTOCOL_ERROR);
8648 ssl_data2.cert_request_info = cert_request.get();
8649 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8650 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8651 session_deps.socket_factory.AddSocketDataProvider(&data2);
8652
8653 // [ssl_]data3 contains the data for the third SSL handshake. When a
8654 // connection to a server fails during an SSL handshake,
8655 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8656 // connection was attempted with TLSv1. This is transparent to the caller
8657 // of the HttpNetworkTransaction. Because this test failure is due to
8658 // requiring a client certificate, this fallback handshake should also
8659 // fail.
8660 SSLSocketDataProvider ssl_data3(true /* async */,
8661 net::ERR_SSL_PROTOCOL_ERROR);
8662 ssl_data3.cert_request_info = cert_request.get();
8663 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8664 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8665 session_deps.socket_factory.AddSocketDataProvider(&data3);
8666
8667 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8668 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8669
[email protected]bd0b6772011-01-11 19:59:308670 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:418671 TestCompletionCallback callback;
8672 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308673 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8674
8675 // Complete the SSL handshake, which should abort due to requiring a
8676 // client certificate.
8677 rv = callback.WaitForResult();
8678 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8679
8680 // Indicate that no certificate should be supplied. From the perspective
8681 // of SSLClientCertCache, NULL is just as meaningful as a real
8682 // certificate, so this is the same as supply a
8683 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418684 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308685 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8686
8687 // Ensure the certificate was added to the client auth cache before
8688 // allowing the connection to continue restarting.
8689 scoped_refptr<X509Certificate> client_cert;
8690 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8691 &client_cert));
8692 ASSERT_EQ(NULL, client_cert.get());
8693
8694 // Restart the handshake. This will consume ssl_data2, which fails, and
8695 // then consume ssl_data3, which should also fail. The result code is
8696 // checked against what ssl_data3 should return.
8697 rv = callback.WaitForResult();
8698 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8699
8700 // Ensure that the client certificate is removed from the cache on a
8701 // handshake failure.
8702 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8703 &client_cert));
8704}
8705
8706// Ensure that a client certificate is removed from the SSL client auth
8707// cache when:
8708// 1) No proxy is involved.
8709// 2) TLS False Start is enabled.
8710// 3) The initial TLS handshake requests a client certificate.
8711// 4) The client supplies an invalid/unacceptable certificate.
8712TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278713 net::HttpRequestInfo request_info;
8714 request_info.url = GURL("https://www.example.com/");
8715 request_info.method = "GET";
8716 request_info.load_flags = net::LOAD_NORMAL;
8717
[email protected]bd0b6772011-01-11 19:59:308718 SessionDependencies session_deps;
8719
8720 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8721 cert_request->host_and_port = "www.example.com:443";
8722
8723 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8724 // return successfully after reading up to the peer's Certificate message.
8725 // This is to allow the caller to call SSLClientSocket::Write(), which can
8726 // enqueue application data to be sent in the same packet as the
8727 // ChangeCipherSpec and Finished messages.
8728 // The actual handshake will be finished when SSLClientSocket::Read() is
8729 // called, which expects to process the peer's ChangeCipherSpec and
8730 // Finished messages. If there was an error negotiating with the peer,
8731 // such as due to the peer requiring a client certificate when none was
8732 // supplied, the alert sent by the peer won't be processed until Read() is
8733 // called.
8734
8735 // Like the non-False Start case, when a client certificate is requested by
8736 // the peer, the handshake is aborted during the Connect() call.
8737 // [ssl_]data1 represents the initial SSL handshake with the peer.
8738 SSLSocketDataProvider ssl_data1(true /* async */,
8739 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8740 ssl_data1.cert_request_info = cert_request.get();
8741 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8742 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8743 session_deps.socket_factory.AddSocketDataProvider(&data1);
8744
8745 // When a client certificate is supplied, Connect() will not be aborted
8746 // when the peer requests the certificate. Instead, the handshake will
8747 // artificially succeed, allowing the caller to write the HTTP request to
8748 // the socket. The handshake messages are not processed until Read() is
8749 // called, which then detects that the handshake was aborted, due to the
8750 // peer sending a handshake_failure because it requires a client
8751 // certificate.
8752 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8753 ssl_data2.cert_request_info = cert_request.get();
8754 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8755 net::MockRead data2_reads[] = {
8756 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8757 };
8758 net::StaticSocketDataProvider data2(
8759 data2_reads, arraysize(data2_reads), NULL, 0);
8760 session_deps.socket_factory.AddSocketDataProvider(&data2);
8761
8762 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8763 // the data for the SSL handshake once the TLSv1 connection falls back to
8764 // SSLv3. It has the same behaviour as [ssl_]data2.
8765 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8766 ssl_data3.cert_request_info = cert_request.get();
8767 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8768 net::StaticSocketDataProvider data3(
8769 data2_reads, arraysize(data2_reads), NULL, 0);
8770 session_deps.socket_factory.AddSocketDataProvider(&data3);
8771
8772 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8773 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8774
[email protected]bd0b6772011-01-11 19:59:308775 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:418776 TestCompletionCallback callback;
8777 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308778 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8779
8780 // Complete the SSL handshake, which should abort due to requiring a
8781 // client certificate.
8782 rv = callback.WaitForResult();
8783 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8784
8785 // Indicate that no certificate should be supplied. From the perspective
8786 // of SSLClientCertCache, NULL is just as meaningful as a real
8787 // certificate, so this is the same as supply a
8788 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418789 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308790 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8791
8792 // Ensure the certificate was added to the client auth cache before
8793 // allowing the connection to continue restarting.
8794 scoped_refptr<X509Certificate> client_cert;
8795 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8796 &client_cert));
8797 ASSERT_EQ(NULL, client_cert.get());
8798
8799
8800 // Restart the handshake. This will consume ssl_data2, which fails, and
8801 // then consume ssl_data3, which should also fail. The result code is
8802 // checked against what ssl_data3 should return.
8803 rv = callback.WaitForResult();
8804 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8805
8806 // Ensure that the client certificate is removed from the cache on a
8807 // handshake failure.
8808 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8809 &client_cert));
8810}
8811
[email protected]8c405132011-01-11 22:03:188812// Ensure that a client certificate is removed from the SSL client auth
8813// cache when:
8814// 1) An HTTPS proxy is involved.
8815// 3) The HTTPS proxy requests a client certificate.
8816// 4) The client supplies an invalid/unacceptable certificate for the
8817// proxy.
8818// The test is repeated twice, first for connecting to an HTTPS endpoint,
8819// then for connecting to an HTTP endpoint.
8820TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8821 SessionDependencies session_deps(
8822 ProxyService::CreateFixed("https://proxy:70"));
8823 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8824 session_deps.net_log = log.bound().net_log();
8825
8826 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8827 cert_request->host_and_port = "proxy:70";
8828
8829 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8830 // [ssl_]data[1-3]. Rather than represending the endpoint
8831 // (www.example.com:443), they represent failures with the HTTPS proxy
8832 // (proxy:70).
8833 SSLSocketDataProvider ssl_data1(true /* async */,
8834 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8835 ssl_data1.cert_request_info = cert_request.get();
8836 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8837 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8838 session_deps.socket_factory.AddSocketDataProvider(&data1);
8839
8840 SSLSocketDataProvider ssl_data2(true /* async */,
8841 net::ERR_SSL_PROTOCOL_ERROR);
8842 ssl_data2.cert_request_info = cert_request.get();
8843 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8844 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8845 session_deps.socket_factory.AddSocketDataProvider(&data2);
8846
8847 SSLSocketDataProvider ssl_data3(true /* async */,
8848 net::ERR_SSL_PROTOCOL_ERROR);
8849 ssl_data3.cert_request_info = cert_request.get();
8850 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8851 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8852 session_deps.socket_factory.AddSocketDataProvider(&data3);
8853
8854 net::HttpRequestInfo requests[2];
8855 requests[0].url = GURL("https://www.example.com/");
8856 requests[0].method = "GET";
8857 requests[0].load_flags = net::LOAD_NORMAL;
8858
8859 requests[1].url = GURL("http://www.example.com/");
8860 requests[1].method = "GET";
8861 requests[1].load_flags = net::LOAD_NORMAL;
8862
8863 for (size_t i = 0; i < arraysize(requests); ++i) {
8864 session_deps.socket_factory.ResetNextMockIndexes();
8865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8866 scoped_ptr<HttpNetworkTransaction> trans(
8867 new HttpNetworkTransaction(session));
8868
8869 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:418870 TestCompletionCallback callback;
8871 int rv = trans->Start(
8872 &requests[i], callback.callback(), net::BoundNetLog());
[email protected]8c405132011-01-11 22:03:188873 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8874
8875 // Complete the SSL handshake, which should abort due to requiring a
8876 // client certificate.
8877 rv = callback.WaitForResult();
8878 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8879
8880 // Indicate that no certificate should be supplied. From the perspective
8881 // of SSLClientCertCache, NULL is just as meaningful as a real
8882 // certificate, so this is the same as supply a
8883 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418884 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]8c405132011-01-11 22:03:188885 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8886
8887 // Ensure the certificate was added to the client auth cache before
8888 // allowing the connection to continue restarting.
8889 scoped_refptr<X509Certificate> client_cert;
8890 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8891 &client_cert));
8892 ASSERT_EQ(NULL, client_cert.get());
8893 // Ensure the certificate was NOT cached for the endpoint. This only
8894 // applies to HTTPS requests, but is fine to check for HTTP requests.
8895 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8896 &client_cert));
8897
8898 // Restart the handshake. This will consume ssl_data2, which fails, and
8899 // then consume ssl_data3, which should also fail. The result code is
8900 // checked against what ssl_data3 should return.
8901 rv = callback.WaitForResult();
8902 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8903
8904 // Now that the new handshake has failed, ensure that the client
8905 // certificate was removed from the client auth cache.
8906 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8907 &client_cert));
8908 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8909 &client_cert));
8910 }
8911}
8912
[email protected]5c288bc2011-07-26 15:12:058913void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8914 SpdySessionPoolPeer* pool_peer,
8915 std::string host,
8916 int port,
8917 std::string iplist) {
8918 // Create a host resolver dependency that returns address |iplist| for
8919 // resolutions of |host|.
8920 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:048921
[email protected]5c288bc2011-07-26 15:12:058922 // Setup a HostPortProxyPair.
8923 HostPortPair host_port_pair(host, port);
8924 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
8925 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:048926
[email protected]5c288bc2011-07-26 15:12:058927 // Resolve the host and port.
8928 AddressList addresses;
8929 HostResolver::RequestInfo info(host_port_pair);
[email protected]aa22b242011-11-16 18:58:298930 TestCompletionCallback callback;
8931 int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:478932 BoundNetLog());
8933 if (rv == ERR_IO_PENDING)
8934 rv = callback.WaitForResult();
8935 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:048936
[email protected]5c288bc2011-07-26 15:12:058937 // Add the first address as an alias. It would have been better to call
8938 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
8939 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
8940 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
8941 // the |pair|.
8942 const addrinfo* address = addresses.head();
8943 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:048944}
8945
[email protected]e3ceb682011-06-28 23:55:468946TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
8947 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348948 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:468949
8950 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
8951 SessionDependencies session_deps;
8952 MockCachingHostResolver host_resolver;
8953 net::HttpNetworkSession::Params params;
8954 params.client_socket_factory = &session_deps.socket_factory;
8955 params.host_resolver = &host_resolver;
8956 params.cert_verifier = session_deps.cert_verifier.get();
8957 params.proxy_service = session_deps.proxy_service.get();
8958 params.ssl_config_service = session_deps.ssl_config_service;
8959 params.http_auth_handler_factory =
8960 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:538961 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:468962 params.net_log = session_deps.net_log;
8963 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268964 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8965 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468966
8967 SSLSocketDataProvider ssl(true, OK);
8968 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208969 ssl.next_proto = "spdy/2.1";
[email protected]e3ceb682011-06-28 23:55:468970 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208971 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]e3ceb682011-06-28 23:55:468972 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8973
8974 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
8975 "https://www.google.com", false, 1, LOWEST));
8976 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
8977 "https://www.gmail.com", false, 3, LOWEST));
8978 MockWrite spdy_writes[] = {
8979 CreateMockWrite(*host1_req, 1),
8980 CreateMockWrite(*host2_req, 4),
8981 };
8982 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8983 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
8984 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
8985 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
8986 MockRead spdy_reads[] = {
8987 CreateMockRead(*host1_resp, 2),
8988 CreateMockRead(*host1_resp_body, 3),
8989 CreateMockRead(*host2_resp, 5),
8990 CreateMockRead(*host2_resp_body, 6),
8991 MockRead(true, 0, 7),
8992 };
8993
[email protected]a1595312012-01-22 03:25:048994 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:468995 new OrderedSocketData(
8996 spdy_reads, arraysize(spdy_reads),
8997 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048998 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:468999
[email protected]aa22b242011-11-16 18:58:299000 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469001 HttpRequestInfo request1;
9002 request1.method = "GET";
9003 request1.url = GURL("https://www.google.com/");
9004 request1.load_flags = 0;
9005 HttpNetworkTransaction trans1(session);
9006
[email protected]49639fa2011-12-20 23:22:419007 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469008 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419009 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469010
9011 const HttpResponseInfo* response = trans1.GetResponseInfo();
9012 ASSERT_TRUE(response != NULL);
9013 ASSERT_TRUE(response->headers != NULL);
9014 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9015
9016 std::string response_data;
9017 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9018 EXPECT_EQ("hello!", response_data);
9019
9020 // Preload www.gmail.com into HostCache.
9021 HostPortPair host_port("www.gmail.com", 443);
9022 HostResolver::RequestInfo resolve_info(host_port);
9023 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299024 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479025 BoundNetLog());
9026 EXPECT_EQ(ERR_IO_PENDING, rv);
9027 rv = callback.WaitForResult();
9028 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469029
[email protected]5c288bc2011-07-26 15:12:059030 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9031 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9032 // (www.google.com, 443).
9033 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
9034 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049035
[email protected]e3ceb682011-06-28 23:55:469036 HttpRequestInfo request2;
9037 request2.method = "GET";
9038 request2.url = GURL("https://www.gmail.com/");
9039 request2.load_flags = 0;
9040 HttpNetworkTransaction trans2(session);
9041
[email protected]49639fa2011-12-20 23:22:419042 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469043 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419044 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469045
9046 response = trans2.GetResponseInfo();
9047 ASSERT_TRUE(response != NULL);
9048 ASSERT_TRUE(response->headers != NULL);
9049 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9050 EXPECT_TRUE(response->was_fetched_via_spdy);
9051 EXPECT_TRUE(response->was_npn_negotiated);
9052 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9053 EXPECT_EQ("hello!", response_data);
9054
[email protected]5285d972011-10-18 18:56:349055 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469056 HttpStreamFactory::set_use_alternate_protocols(false);
9057}
9058
9059class OneTimeCachingHostResolver : public net::HostResolver {
9060 public:
9061 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9062 : host_port_(host_port) {}
9063 virtual ~OneTimeCachingHostResolver() {}
9064
9065 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9066
9067 // HostResolver methods:
9068 virtual int Resolve(const RequestInfo& info,
9069 AddressList* addresses,
[email protected]aa22b242011-11-16 18:58:299070 const CompletionCallback& callback,
[email protected]e3ceb682011-06-28 23:55:469071 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:409072 const BoundNetLog& net_log) OVERRIDE {
9073 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:469074 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:409075 }
9076
9077 virtual int ResolveFromCache(const RequestInfo& info,
9078 AddressList* addresses,
9079 const BoundNetLog& net_log) OVERRIDE {
9080 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9081 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:099082 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:469083 return rv;
9084 }
9085
[email protected]95a214c2011-08-04 21:50:409086 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469087 host_resolver_.CancelRequest(req);
9088 }
9089
[email protected]46da33be2011-07-19 21:58:049090 MockCachingHostResolver* GetMockHostResolver() {
9091 return &host_resolver_;
9092 }
9093
[email protected]e3ceb682011-06-28 23:55:469094 private:
9095 MockCachingHostResolver host_resolver_;
9096 const HostPortPair host_port_;
9097};
9098
9099TEST_F(HttpNetworkTransactionTest,
9100 UseIPConnectionPoolingWithHostCacheExpiration) {
9101 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349102 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469103
9104 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9105 SessionDependencies session_deps;
9106 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9107 net::HttpNetworkSession::Params params;
9108 params.client_socket_factory = &session_deps.socket_factory;
9109 params.host_resolver = &host_resolver;
9110 params.cert_verifier = session_deps.cert_verifier.get();
9111 params.proxy_service = session_deps.proxy_service.get();
9112 params.ssl_config_service = session_deps.ssl_config_service;
9113 params.http_auth_handler_factory =
9114 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539115 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469116 params.net_log = session_deps.net_log;
9117 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269118 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9119 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469120
9121 SSLSocketDataProvider ssl(true, OK);
9122 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:209123 ssl.next_proto = "spdy/2.1";
[email protected]e3ceb682011-06-28 23:55:469124 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:209125 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]e3ceb682011-06-28 23:55:469126 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9127
9128 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9129 "https://www.google.com", false, 1, LOWEST));
9130 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9131 "https://www.gmail.com", false, 3, LOWEST));
9132 MockWrite spdy_writes[] = {
9133 CreateMockWrite(*host1_req, 1),
9134 CreateMockWrite(*host2_req, 4),
9135 };
9136 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9137 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9138 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9139 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9140 MockRead spdy_reads[] = {
9141 CreateMockRead(*host1_resp, 2),
9142 CreateMockRead(*host1_resp_body, 3),
9143 CreateMockRead(*host2_resp, 5),
9144 CreateMockRead(*host2_resp_body, 6),
9145 MockRead(true, 0, 7),
9146 };
9147
[email protected]a1595312012-01-22 03:25:049148 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:469149 new OrderedSocketData(
9150 spdy_reads, arraysize(spdy_reads),
9151 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:049152 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:469153
[email protected]aa22b242011-11-16 18:58:299154 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469155 HttpRequestInfo request1;
9156 request1.method = "GET";
9157 request1.url = GURL("https://www.google.com/");
9158 request1.load_flags = 0;
9159 HttpNetworkTransaction trans1(session);
9160
[email protected]49639fa2011-12-20 23:22:419161 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469162 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419163 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469164
9165 const HttpResponseInfo* response = trans1.GetResponseInfo();
9166 ASSERT_TRUE(response != NULL);
9167 ASSERT_TRUE(response->headers != NULL);
9168 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9169
9170 std::string response_data;
9171 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9172 EXPECT_EQ("hello!", response_data);
9173
9174 // Preload cache entries into HostCache.
9175 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9176 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299177 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479178 BoundNetLog());
9179 EXPECT_EQ(ERR_IO_PENDING, rv);
9180 rv = callback.WaitForResult();
9181 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469182
9183 HttpRequestInfo request2;
9184 request2.method = "GET";
9185 request2.url = GURL("https://www.gmail.com/");
9186 request2.load_flags = 0;
9187 HttpNetworkTransaction trans2(session);
9188
[email protected]5c288bc2011-07-26 15:12:059189 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9190 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9191 // (www.google.com, 443).
9192 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9193 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049194
[email protected]49639fa2011-12-20 23:22:419195 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469196 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419197 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469198
9199 response = trans2.GetResponseInfo();
9200 ASSERT_TRUE(response != NULL);
9201 ASSERT_TRUE(response->headers != NULL);
9202 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9203 EXPECT_TRUE(response->was_fetched_via_spdy);
9204 EXPECT_TRUE(response->was_npn_negotiated);
9205 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9206 EXPECT_EQ("hello!", response_data);
9207
[email protected]5285d972011-10-18 18:56:349208 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469209 HttpStreamFactory::set_use_alternate_protocols(false);
9210}
9211
[email protected]5a60c8b2011-10-19 20:14:299212TEST_F(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
9213 MockRead data_reads1[] = {
9214 MockRead(false, ERR_PIPELINE_EVICTION),
9215 };
9216 MockRead data_reads2[] = {
9217 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9218 MockRead("hello world"),
9219 MockRead(false, OK),
9220 };
9221 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
9222 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
9223 StaticSocketDataProvider* data[] = { &data1, &data2 };
9224
9225 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9226
9227 EXPECT_EQ(OK, out.rv);
9228 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9229 EXPECT_EQ("hello world", out.response_data);
9230}
9231
9232TEST_F(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
9233 MockWrite data_writes1[] = {
9234 MockWrite(false, ERR_PIPELINE_EVICTION),
9235 };
9236 MockWrite data_writes2[] = {
9237 MockWrite("GET / HTTP/1.1\r\n"
9238 "Host: www.google.com\r\n"
9239 "Connection: keep-alive\r\n\r\n"),
9240 };
9241 MockRead data_reads2[] = {
9242 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9243 MockRead("hello world"),
9244 MockRead(false, OK),
9245 };
9246 StaticSocketDataProvider data1(NULL, 0,
9247 data_writes1, arraysize(data_writes1));
9248 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9249 data_writes2, arraysize(data_writes2));
9250 StaticSocketDataProvider* data[] = { &data1, &data2 };
9251
9252 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9253
9254 EXPECT_EQ(OK, out.rv);
9255 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9256 EXPECT_EQ("hello world", out.response_data);
9257}
9258
[email protected]89ceba9a2009-03-21 03:46:069259} // namespace net