blob: 45efec712eba5e8e0a9097a5697857dbeb4db90f [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]8ddf8322012-02-23 18:08:06434 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06447 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06460 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06473 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06486 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06503 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06516 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06532 MockRead(SYNCHRONOUS, 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"),
[email protected]8ddf8322012-02-23 18:08:06551 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:57552 };
[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"),
[email protected]8ddf8322012-02-23 18:08:06647 MockRead(SYNCHRONOUS, OK),
[email protected]9fe44f52010-09-23 18:36:00648 };
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"),
[email protected]8ddf8322012-02-23 18:08:06708 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:55709 };
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"),
[email protected]8ddf8322012-02-23 18:08:06745 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:55746 };
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"),
[email protected]8ddf8322012-02-23 18:08:06759 MockRead(SYNCHRONOUS, OK),
[email protected]1628fe92011-10-04 23:04:55760 };
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]8ddf8322012-02-23 18:08:06790 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06837 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06891 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:06933 MockRead(SYNCHRONOUS, 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[] = {
[email protected]8ddf8322012-02-23 18:08:06969 MockRead(SYNCHRONOUS, "HTTP/1.0 100 Continue\r\n"),
970 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:38971 };
[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[] = {
[email protected]8ddf8322012-02-23 18:08:061000 MockRead(ASYNC, 0),
[email protected]ee9410e72010-01-07 01:42:381001 };
[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]8ddf8322012-02-23 18:08:061039 MockRead(ASYNC, 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]8ddf8322012-02-23 18:08:061057 MockRead(ASYNC, 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) {
[email protected]8ddf8322012-02-23 18:08:061091 MockWrite write_failure(ASYNC, ERR_SOCKET_NOT_CONNECTED);
[email protected]202965992011-12-07 23:04:511092 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1093}
1094
[email protected]3d2a59b2008-09-26 19:44:251095TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]8ddf8322012-02-23 18:08:061096 MockRead read_failure(ASYNC, 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]8ddf8322012-02-23 18:08:061101 MockRead read_failure(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:061116 MockRead(ASYNC, 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]8ddf8322012-02-23 18:08:061119 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:061147 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:061150 MockRead(SYNCHRONOUS, 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[] = {
[email protected]8ddf8322012-02-23 18:08:061192 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]fc31d6a42010-06-24 18:05:131193 };
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]8ddf8322012-02-23 18:08:061280 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:061297 MockRead(SYNCHRONOUS, 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"),
[email protected]8ddf8322012-02-23 18:08:061356 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]861fcd52009-08-26 02:33:461357 };
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[] = {
[email protected]8ddf8322012-02-23 18:08:061416 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:461417 };
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[] = {
[email protected]8ddf8322012-02-23 18:08:061492 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:461493 };
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"),
[email protected]8ddf8322012-02-23 18:08:061565 MockRead(ASYNC, large_body_string.data(), large_body_string.size()),
[email protected]2d2697f92009-02-18 21:00:321566
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[] = {
[email protected]8ddf8322012-02-23 18:08:061576 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]2d0a4f92011-05-05 16:38:461577 };
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.
[email protected]8ddf8322012-02-23 18:08:061643 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]11203f012009-11-12 23:02:311644 MockRead("Unauthorized\r\n"),
[email protected]8ddf8322012-02-23 18:08:061645 MockRead(SYNCHRONOUS, OK), // The server closes the connection.
[email protected]11203f012009-11-12 23:02:311646 };
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"),
[email protected]8ddf8322012-02-23 18:08:061746 MockRead(SYNCHRONOUS, "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);
[email protected]8ddf8322012-02-23 18:08:061752 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]394816e92010-08-03 07:38:591753 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]8ddf8322012-02-23 18:08:061851 MockRead(SYNCHRONOUS, 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]8ddf8322012-02-23 18:08:061935 MockRead(SYNCHRONOUS, 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"),
[email protected]8ddf8322012-02-23 18:08:061990 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]8fdbcd22010-05-05 02:54:521991 };
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"),
[email protected]8ddf8322012-02-23 18:08:062040 MockRead(SYNCHRONOUS, OK),
[email protected]7a67a8152010-11-05 18:31:102041 };
2042
2043 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2044 data_writes1, arraysize(data_writes1));
2045 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:062046 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]7a67a8152010-11-05 18:31:102047 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"),
[email protected]8ddf8322012-02-23 18:08:062093 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:462094 };
2095
2096 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2097 data_writes1, arraysize(data_writes1));
2098 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:062099 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:462100 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),
[email protected]8ddf8322012-02-23 18:08:062148 MockRead(ASYNC, 0, 0),
[email protected]7642b5ae2010-09-01 20:55:172149 };
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
[email protected]8ddf8322012-02-23 18:08:062158 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:512159 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]7642b5ae2010-09-01 20:55:172160 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2161
[email protected]49639fa2011-12-20 23:22:412162 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:172163
[email protected]0b0bf032010-09-21 18:08:502164 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2165
[email protected]49639fa2011-12-20 23:22:412166 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:172167 EXPECT_EQ(ERR_IO_PENDING, rv);
2168
2169 rv = callback1.WaitForResult();
2170 EXPECT_EQ(OK, rv);
2171
2172 const HttpResponseInfo* response = trans->GetResponseInfo();
2173 ASSERT_TRUE(response != NULL);
2174 ASSERT_TRUE(response->headers != NULL);
2175 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2176
2177 std::string response_data;
2178 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2179 EXPECT_EQ(net::kUploadData, response_data);
2180}
2181
[email protected]dc7bd1c52010-11-12 00:01:132182// Test a SPDY get through an HTTPS Proxy.
2183TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272184 HttpRequestInfo request;
2185 request.method = "GET";
2186 request.url = GURL("http://www.google.com/");
2187 request.load_flags = 0;
2188
[email protected]79cb5c12011-09-12 13:12:042189 // Configure against https proxy server "myproxy:70".
[email protected]dc7bd1c52010-11-12 00:01:132190 SessionDependencies session_deps(
[email protected]79cb5c12011-09-12 13:12:042191 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]dc7bd1c52010-11-12 00:01:132192 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2193 session_deps.net_log = log.bound().net_log();
2194 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2195
[email protected]dc7bd1c52010-11-12 00:01:132196 // The first request will be a bare GET, the second request will be a
2197 // GET with a Proxy-Authorization header.
2198 scoped_ptr<spdy::SpdyFrame> req_get(
2199 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2200 const char* const kExtraAuthorizationHeaders[] = {
2201 "proxy-authorization",
2202 "Basic Zm9vOmJhcg==",
2203 };
2204 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2205 ConstructSpdyGet(
2206 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2207 false, 3, LOWEST, false));
2208 MockWrite spdy_writes[] = {
2209 CreateMockWrite(*req_get, 1),
2210 CreateMockWrite(*req_get_authorization, 4),
2211 };
2212
2213 // The first response is a 407 proxy authentication challenge, and the second
2214 // response will be a 200 response since the second request includes a valid
2215 // Authorization header.
2216 const char* const kExtraAuthenticationHeaders[] = {
[email protected]fb9e4312012-02-17 06:27:262217 "proxy-authenticate",
[email protected]dc7bd1c52010-11-12 00:01:132218 "Basic realm=\"MyRealm1\""
2219 };
2220 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2221 ConstructSpdySynReplyError(
2222 "407 Proxy Authentication Required",
2223 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2224 1));
2225 scoped_ptr<spdy::SpdyFrame> body_authentication(
2226 ConstructSpdyBodyFrame(1, true));
2227 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2228 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2229 MockRead spdy_reads[] = {
2230 CreateMockRead(*resp_authentication, 2),
2231 CreateMockRead(*body_authentication, 3),
2232 CreateMockRead(*resp_data, 5),
2233 CreateMockRead(*body_data, 6),
[email protected]8ddf8322012-02-23 18:08:062234 MockRead(ASYNC, 0, 7),
[email protected]dc7bd1c52010-11-12 00:01:132235 };
2236
[email protected]a1595312012-01-22 03:25:042237 scoped_ptr<OrderedSocketData> data(
[email protected]dc7bd1c52010-11-12 00:01:132238 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2239 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042240 session_deps.socket_factory.AddSocketDataProvider(data.get());
[email protected]dc7bd1c52010-11-12 00:01:132241
[email protected]8ddf8322012-02-23 18:08:062242 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:512243 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]dc7bd1c52010-11-12 00:01:132244 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2245
[email protected]49639fa2011-12-20 23:22:412246 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:132247
2248 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2249
[email protected]49639fa2011-12-20 23:22:412250 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:132251 EXPECT_EQ(ERR_IO_PENDING, rv);
2252
2253 rv = callback1.WaitForResult();
2254 EXPECT_EQ(OK, rv);
2255
2256 const HttpResponseInfo* const response = trans->GetResponseInfo();
2257
2258 ASSERT_TRUE(response != NULL);
2259 ASSERT_TRUE(response->headers != NULL);
2260 EXPECT_EQ(407, response->headers->response_code());
2261 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:042262 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:132263
[email protected]49639fa2011-12-20 23:22:412264 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:132265
[email protected]49639fa2011-12-20 23:22:412266 rv = trans->RestartWithAuth(
2267 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:132268 EXPECT_EQ(ERR_IO_PENDING, rv);
2269
2270 rv = callback2.WaitForResult();
2271 EXPECT_EQ(OK, rv);
2272
2273 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2274
2275 ASSERT_TRUE(response_restart != NULL);
2276 ASSERT_TRUE(response_restart->headers != NULL);
2277 EXPECT_EQ(200, response_restart->headers->response_code());
2278 // The password prompt info should not be set.
2279 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2280}
2281
[email protected]d9da5fe2010-10-13 22:37:162282// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2283TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272284 HttpRequestInfo request;
2285 request.method = "GET";
2286 request.url = GURL("https://www.google.com/");
2287 request.load_flags = 0;
2288
[email protected]d9da5fe2010-10-13 22:37:162289 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112290 SessionDependencies session_deps(ProxyService::CreateFixed(
2291 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162292 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2293 session_deps.net_log = log.bound().net_log();
2294 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2295
2296 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2297
[email protected]d9da5fe2010-10-13 22:37:162298 // CONNECT to www.google.com:443 via SPDY
2299 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2300 // fetch https://www.google.com/ via HTTP
2301
2302 const char get[] = "GET / HTTP/1.1\r\n"
2303 "Host: www.google.com\r\n"
2304 "Connection: keep-alive\r\n\r\n";
2305 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2306 ConstructSpdyBodyFrame(1, get, strlen(get), false));
[email protected]d9da5fe2010-10-13 22:37:162307 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2308 const char resp[] = "HTTP/1.1 200 OK\r\n"
2309 "Content-Length: 10\r\n\r\n";
[email protected]d9da5fe2010-10-13 22:37:162310 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2311 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2312 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2313 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
[email protected]8d2f7012012-02-16 00:08:042314 scoped_ptr<spdy::SpdyFrame> window_update(
2315 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2316
2317 MockWrite spdy_writes[] = {
2318 CreateMockWrite(*connect, 1),
2319 CreateMockWrite(*wrapped_get, 3),
2320 CreateMockWrite(*window_update, 5)
2321 };
2322
[email protected]d9da5fe2010-10-13 22:37:162323 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062324 CreateMockRead(*conn_resp, 2, ASYNC),
2325 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2326 CreateMockRead(*wrapped_body, 6, ASYNC),
2327 CreateMockRead(*wrapped_body, 7, ASYNC),
2328 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:162329 };
2330
[email protected]a1595312012-01-22 03:25:042331 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162332 new OrderedSocketData(
2333 spdy_reads, arraysize(spdy_reads),
2334 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042335 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162336
[email protected]8ddf8322012-02-23 18:08:062337 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:512338 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162339 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:062340 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]d9da5fe2010-10-13 22:37:162341 ssl2.was_npn_negotiated = false;
[email protected]c30bcce2011-12-20 17:50:512342 ssl2.protocol_negotiated = SSLClientSocket::kProtoUnknown;
[email protected]d9da5fe2010-10-13 22:37:162343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2344
[email protected]49639fa2011-12-20 23:22:412345 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162346
[email protected]49639fa2011-12-20 23:22:412347 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162348 EXPECT_EQ(ERR_IO_PENDING, rv);
2349
2350 rv = callback1.WaitForResult();
2351 EXPECT_EQ(OK, rv);
2352
2353 const HttpResponseInfo* response = trans->GetResponseInfo();
2354 ASSERT_TRUE(response != NULL);
2355 ASSERT_TRUE(response->headers != NULL);
2356 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2357
2358 std::string response_data;
2359 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2360 EXPECT_EQ("1234567890", response_data);
2361}
2362
2363// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2364TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272365 HttpRequestInfo request;
2366 request.method = "GET";
2367 request.url = GURL("https://www.google.com/");
2368 request.load_flags = 0;
2369
[email protected]d9da5fe2010-10-13 22:37:162370 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112371 SessionDependencies session_deps(ProxyService::CreateFixed(
2372 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162373 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2374 session_deps.net_log = log.bound().net_log();
2375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2376
2377 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2378
[email protected]d9da5fe2010-10-13 22:37:162379 // CONNECT to www.google.com:443 via SPDY
2380 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2381 // fetch https://www.google.com/ via SPDY
2382 const char* const kMyUrl = "https://www.google.com/";
2383 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2384 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
[email protected]d9da5fe2010-10-13 22:37:162385 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2386 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2387 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2388 ConstructWrappedSpdyFrame(get_resp, 1));
2389 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2390 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
[email protected]8d2f7012012-02-16 00:08:042391 scoped_ptr<spdy::SpdyFrame> window_update_get_resp(
2392 ConstructSpdyWindowUpdate(1, wrapped_get_resp->length()));
2393 scoped_ptr<spdy::SpdyFrame> window_update_body(
2394 ConstructSpdyWindowUpdate(1, wrapped_body->length()));
2395
2396 MockWrite spdy_writes[] = {
2397 CreateMockWrite(*connect, 1),
2398 CreateMockWrite(*wrapped_get, 3),
2399 CreateMockWrite(*window_update_get_resp, 5),
2400 CreateMockWrite(*window_update_body, 7),
2401 };
2402
[email protected]d9da5fe2010-10-13 22:37:162403 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062404 CreateMockRead(*conn_resp, 2, ASYNC),
2405 CreateMockRead(*wrapped_get_resp, 4, ASYNC),
2406 CreateMockRead(*wrapped_body, 6, ASYNC),
2407 MockRead(ASYNC, 0, 8),
[email protected]d9da5fe2010-10-13 22:37:162408 };
2409
[email protected]a1595312012-01-22 03:25:042410 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162411 new OrderedSocketData(
2412 spdy_reads, arraysize(spdy_reads),
2413 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042414 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162415
[email protected]8ddf8322012-02-23 18:08:062416 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:512417 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162418 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:062419 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:512420 ssl2.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]1ad77dc2012-01-27 03:51:202421 ssl2.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162422 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2423
[email protected]49639fa2011-12-20 23:22:412424 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162425
[email protected]49639fa2011-12-20 23:22:412426 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162427 EXPECT_EQ(ERR_IO_PENDING, rv);
2428
2429 rv = callback1.WaitForResult();
2430 EXPECT_EQ(OK, rv);
2431
2432 const HttpResponseInfo* response = trans->GetResponseInfo();
2433 ASSERT_TRUE(response != NULL);
2434 ASSERT_TRUE(response->headers != NULL);
2435 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2436
2437 std::string response_data;
2438 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2439 EXPECT_EQ(net::kUploadData, response_data);
2440}
2441
2442// Test a SPDY CONNECT failure through an HTTPS Proxy.
2443TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272444 HttpRequestInfo request;
2445 request.method = "GET";
2446 request.url = GURL("https://www.google.com/");
2447 request.load_flags = 0;
2448
[email protected]d9da5fe2010-10-13 22:37:162449 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112450 SessionDependencies session_deps(ProxyService::CreateFixed(
2451 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162452 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2453 session_deps.net_log = log.bound().net_log();
2454 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2455
2456 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2457
[email protected]d9da5fe2010-10-13 22:37:162458 // CONNECT to www.google.com:443 via SPDY
2459 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2460 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2461
2462 MockWrite spdy_writes[] = {
2463 CreateMockWrite(*connect, 1),
2464 CreateMockWrite(*get, 3),
2465 };
2466
2467 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2468 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2469 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:062470 CreateMockRead(*resp, 2, ASYNC),
2471 MockRead(ASYNC, 0, 4),
[email protected]d9da5fe2010-10-13 22:37:162472 };
2473
[email protected]a1595312012-01-22 03:25:042474 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162475 new OrderedSocketData(
2476 spdy_reads, arraysize(spdy_reads),
2477 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042478 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162479
[email protected]8ddf8322012-02-23 18:08:062480 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:512481 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162482 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]8ddf8322012-02-23 18:08:062483 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:512484 ssl2.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]d9da5fe2010-10-13 22:37:162485 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2486
[email protected]49639fa2011-12-20 23:22:412487 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162488
[email protected]49639fa2011-12-20 23:22:412489 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162490 EXPECT_EQ(ERR_IO_PENDING, rv);
2491
2492 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292493 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162494
2495 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502496 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:292497 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162498}
2499
[email protected]2df19bb2010-08-25 20:13:462500// Test the challenge-response-retry sequence through an HTTPS Proxy
2501TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462502 HttpRequestInfo request;
2503 request.method = "GET";
2504 request.url = GURL("http://www.google.com/");
2505 // when the no authentication data flag is set.
2506 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2507
[email protected]79cb5c12011-09-12 13:12:042508 // Configure against https proxy server "myproxy:70".
2509 SessionDependencies session_deps(
2510 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]cb9bf6ca2011-01-28 13:15:272511 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2512 session_deps.net_log = log.bound().net_log();
2513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2514
[email protected]2df19bb2010-08-25 20:13:462515 // Since we have proxy, should use full url
2516 MockWrite data_writes1[] = {
2517 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2518 "Host: www.google.com\r\n"
2519 "Proxy-Connection: keep-alive\r\n\r\n"),
2520
2521 // After calling trans->RestartWithAuth(), this is the request we should
2522 // be issuing -- the final header line contains the credentials.
2523 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2524 "Host: www.google.com\r\n"
2525 "Proxy-Connection: keep-alive\r\n"
2526 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2527 };
2528
2529 // The proxy responds to the GET with a 407, using a persistent
2530 // connection.
2531 MockRead data_reads1[] = {
2532 // No credentials.
2533 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2534 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2535 MockRead("Proxy-Connection: keep-alive\r\n"),
2536 MockRead("Content-Length: 0\r\n\r\n"),
2537
2538 MockRead("HTTP/1.1 200 OK\r\n"),
2539 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2540 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062541 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:462542 };
2543
2544 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2545 data_writes1, arraysize(data_writes1));
2546 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:062547 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:462548 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2549
[email protected]49639fa2011-12-20 23:22:412550 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462551
[email protected]0b0bf032010-09-21 18:08:502552 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2553
[email protected]49639fa2011-12-20 23:22:412554 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:462555 EXPECT_EQ(ERR_IO_PENDING, rv);
2556
2557 rv = callback1.WaitForResult();
2558 EXPECT_EQ(OK, rv);
2559
2560 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502561 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042562 ASSERT_FALSE(response->headers == NULL);
[email protected]2df19bb2010-08-25 20:13:462563 EXPECT_EQ(407, response->headers->response_code());
2564 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042565 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:462566
[email protected]49639fa2011-12-20 23:22:412567 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:462568
[email protected]49639fa2011-12-20 23:22:412569 rv = trans->RestartWithAuth(
2570 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:462571 EXPECT_EQ(ERR_IO_PENDING, rv);
2572
2573 rv = callback2.WaitForResult();
2574 EXPECT_EQ(OK, rv);
2575
2576 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502577 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462578
2579 EXPECT_TRUE(response->headers->IsKeepAlive());
2580 EXPECT_EQ(200, response->headers->response_code());
2581 EXPECT_EQ(100, response->headers->GetContentLength());
2582 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2583
2584 // The password prompt info should not be set.
2585 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2586}
2587
[email protected]ff007e162009-05-23 09:13:152588void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082589 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422590 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082591 request.method = "GET";
2592 request.url = GURL("https://www.google.com/");
2593 request.load_flags = 0;
2594
[email protected]cb9bf6ca2011-01-28 13:15:272595 // Configure against proxy server "myproxy:70".
2596 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2597
2598 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2599
[email protected]c744cf22009-02-27 07:28:082600 // Since we have proxy, should try to establish tunnel.
2601 MockWrite data_writes[] = {
2602 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452603 "Host: www.google.com\r\n"
2604 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082605 };
2606
2607 MockRead data_reads[] = {
2608 status,
2609 MockRead("Content-Length: 10\r\n\r\n"),
2610 // No response body because the test stops reading here.
[email protected]8ddf8322012-02-23 18:08:062611 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082612 };
2613
[email protected]31a2bfe2010-02-09 08:03:392614 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2615 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592616 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082617
[email protected]49639fa2011-12-20 23:22:412618 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:082619
[email protected]0b0bf032010-09-21 18:08:502620 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2621
[email protected]49639fa2011-12-20 23:22:412622 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422623 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082624
2625 rv = callback.WaitForResult();
2626 EXPECT_EQ(expected_status, rv);
2627}
2628
[email protected]ff007e162009-05-23 09:13:152629void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082630 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422631 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082632}
2633
2634TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2635 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2636}
2637
2638TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2639 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2640}
2641
2642TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2643 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2644}
2645
2646TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2647 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2648}
2649
2650TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2651 ConnectStatusHelper(
2652 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2653}
2654
2655TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2656 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2657}
2658
2659TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2660 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2661}
2662
2663TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2664 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2665}
2666
2667TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2668 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2669}
2670
2671TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2672 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2673}
2674
2675TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2676 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2677}
2678
2679TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2680 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2681}
2682
2683TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2684 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2685}
2686
2687TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2688 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2689}
2690
2691TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2692 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2693}
2694
2695TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2696 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2697}
2698
2699TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2700 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2701}
2702
2703TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2704 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2705}
2706
2707TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2708 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2709}
2710
2711TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2712 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2713}
2714
2715TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2716 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2717}
2718
2719TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2720 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2721}
2722
2723TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2724 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2725}
2726
2727TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2728 ConnectStatusHelperWithExpectedStatus(
2729 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542730 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082731}
2732
2733TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2734 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2735}
2736
2737TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2738 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2739}
2740
2741TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2742 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2743}
2744
2745TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2746 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2747}
2748
2749TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2750 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2751}
2752
2753TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2754 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2755}
2756
2757TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2758 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2759}
2760
2761TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2762 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2763}
2764
2765TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2766 ConnectStatusHelper(
2767 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2768}
2769
2770TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2771 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2772}
2773
2774TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2775 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2776}
2777
2778TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2779 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2780}
2781
2782TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2783 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2784}
2785
2786TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2787 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2788}
2789
2790TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2791 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2792}
2793
2794TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2795 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2796}
2797
[email protected]038e9a32008-10-08 22:40:162798// Test the flow when both the proxy server AND origin server require
2799// authentication. Again, this uses basic auth for both since that is
2800// the simplest to mock.
2801TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272802 HttpRequestInfo request;
2803 request.method = "GET";
2804 request.url = GURL("http://www.google.com/");
2805 request.load_flags = 0;
2806
[email protected]81cdfcd2010-10-16 00:49:002807 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012808
[email protected]038e9a32008-10-08 22:40:162809 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422810 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432811 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162812
[email protected]f9ee6b52008-11-08 06:46:232813 MockWrite data_writes1[] = {
2814 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2815 "Host: www.google.com\r\n"
2816 "Proxy-Connection: keep-alive\r\n\r\n"),
2817 };
2818
[email protected]038e9a32008-10-08 22:40:162819 MockRead data_reads1[] = {
2820 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2821 // Give a couple authenticate options (only the middle one is actually
2822 // supported).
[email protected]22927ad2009-09-21 19:56:192823 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162824 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2825 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2826 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2827 // Large content-length -- won't matter, as connection will be reset.
2828 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062829 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162830 };
2831
2832 // After calling trans->RestartWithAuth() the first time, this is the
2833 // request we should be issuing -- the final header line contains the
2834 // proxy's credentials.
2835 MockWrite data_writes2[] = {
2836 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2837 "Host: www.google.com\r\n"
2838 "Proxy-Connection: keep-alive\r\n"
2839 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2840 };
2841
2842 // Now the proxy server lets the request pass through to origin server.
2843 // The origin server responds with a 401.
2844 MockRead data_reads2[] = {
2845 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2846 // Note: We are using the same realm-name as the proxy server. This is
2847 // completely valid, as realms are unique across hosts.
2848 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2849 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2850 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062851 MockRead(SYNCHRONOUS, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162852 };
2853
2854 // After calling trans->RestartWithAuth() the second time, we should send
2855 // the credentials for both the proxy and origin server.
2856 MockWrite data_writes3[] = {
2857 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2858 "Host: www.google.com\r\n"
2859 "Proxy-Connection: keep-alive\r\n"
2860 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2861 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2862 };
2863
2864 // Lastly we get the desired content.
2865 MockRead data_reads3[] = {
2866 MockRead("HTTP/1.0 200 OK\r\n"),
2867 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2868 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:062869 MockRead(SYNCHRONOUS, OK),
[email protected]038e9a32008-10-08 22:40:162870 };
2871
[email protected]31a2bfe2010-02-09 08:03:392872 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2873 data_writes1, arraysize(data_writes1));
2874 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2875 data_writes2, arraysize(data_writes2));
2876 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2877 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592878 session_deps.socket_factory.AddSocketDataProvider(&data1);
2879 session_deps.socket_factory.AddSocketDataProvider(&data2);
2880 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162881
[email protected]49639fa2011-12-20 23:22:412882 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162883
[email protected]49639fa2011-12-20 23:22:412884 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162886
2887 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422888 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162889
[email protected]1c773ea12009-04-28 19:58:422890 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502891 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042892 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162893
[email protected]49639fa2011-12-20 23:22:412894 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162895
[email protected]49639fa2011-12-20 23:22:412896 rv = trans->RestartWithAuth(
2897 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162899
2900 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422901 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162902
2903 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502904 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042905 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162906
[email protected]49639fa2011-12-20 23:22:412907 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:162908
[email protected]49639fa2011-12-20 23:22:412909 rv = trans->RestartWithAuth(
2910 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:422911 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162912
2913 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422914 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162915
2916 response = trans->GetResponseInfo();
2917 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2918 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162919}
[email protected]4ddaf2502008-10-23 18:26:192920
[email protected]ea9dc9a2009-09-05 00:43:322921// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2922// can't hook into its internals to cause it to generate predictable NTLM
2923// authorization headers.
2924#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292925// The NTLM authentication unit tests were generated by capturing the HTTP
2926// requests and responses using Fiddler 2 and inspecting the generated random
2927// bytes in the debugger.
2928
2929// Enter the correct password and authenticate successfully.
2930TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422931 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242932 request.method = "GET";
2933 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2934 request.load_flags = 0;
2935
[email protected]cb9bf6ca2011-01-28 13:15:272936 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2937 MockGetHostName);
2938 SessionDependencies session_deps;
2939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2940
[email protected]3f918782009-02-28 01:29:242941 MockWrite data_writes1[] = {
2942 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2943 "Host: 172.22.68.17\r\n"
2944 "Connection: keep-alive\r\n\r\n"),
2945 };
2946
2947 MockRead data_reads1[] = {
2948 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042949 // Negotiate and NTLM are often requested together. However, we only want
2950 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2951 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242952 MockRead("WWW-Authenticate: NTLM\r\n"),
2953 MockRead("Connection: close\r\n"),
2954 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362955 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242956 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:062957 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242958 };
2959
2960 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222961 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242962 // request we should be issuing -- the final header line contains a Type
2963 // 1 message.
2964 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2965 "Host: 172.22.68.17\r\n"
2966 "Connection: keep-alive\r\n"
2967 "Authorization: NTLM "
2968 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2969
2970 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2971 // (the credentials for the origin server). The second request continues
2972 // on the same connection.
2973 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2974 "Host: 172.22.68.17\r\n"
2975 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292976 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2977 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2978 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2979 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2980 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242981 };
2982
2983 MockRead data_reads2[] = {
2984 // The origin server responds with a Type 2 message.
2985 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2986 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292987 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242988 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2989 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2990 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2991 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2992 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2993 "BtAAAAAAA=\r\n"),
2994 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362995 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242996 MockRead("You are not authorized to view this page\r\n"),
2997
2998 // Lastly we get the desired content.
2999 MockRead("HTTP/1.1 200 OK\r\n"),
3000 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3001 MockRead("Content-Length: 13\r\n\r\n"),
3002 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:063003 MockRead(SYNCHRONOUS, OK),
[email protected]3f918782009-02-28 01:29:243004 };
3005
[email protected]31a2bfe2010-02-09 08:03:393006 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3007 data_writes1, arraysize(data_writes1));
3008 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3009 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593010 session_deps.socket_factory.AddSocketDataProvider(&data1);
3011 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:243012
[email protected]49639fa2011-12-20 23:22:413013 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:243014
[email protected]0b0bf032010-09-21 18:08:503015 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3016
[email protected]49639fa2011-12-20 23:22:413017 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423018 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243019
3020 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423021 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243022
[email protected]0757e7702009-03-27 04:00:223023 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3024
[email protected]1c773ea12009-04-28 19:58:423025 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043026 ASSERT_FALSE(response == NULL);
3027 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:243028
[email protected]49639fa2011-12-20 23:22:413029 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:253030
[email protected]f3cf9802011-10-28 18:44:583031 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413032 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:253033 EXPECT_EQ(ERR_IO_PENDING, rv);
3034
3035 rv = callback2.WaitForResult();
3036 EXPECT_EQ(OK, rv);
3037
3038 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3039
3040 response = trans->GetResponseInfo();
3041 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:253042 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3043
[email protected]49639fa2011-12-20 23:22:413044 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:243045
[email protected]49639fa2011-12-20 23:22:413046 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423047 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243048
[email protected]0757e7702009-03-27 04:00:223049 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423050 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243051
3052 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503053 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:243054 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3055 EXPECT_EQ(13, response->headers->GetContentLength());
3056}
3057
[email protected]385a4672009-03-11 22:21:293058// Enter a wrong password, and then the correct one.
3059TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:423060 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:293061 request.method = "GET";
3062 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3063 request.load_flags = 0;
3064
[email protected]cb9bf6ca2011-01-28 13:15:273065 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3066 MockGetHostName);
3067 SessionDependencies session_deps;
3068 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3069
[email protected]385a4672009-03-11 22:21:293070 MockWrite data_writes1[] = {
3071 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3072 "Host: 172.22.68.17\r\n"
3073 "Connection: keep-alive\r\n\r\n"),
3074 };
3075
3076 MockRead data_reads1[] = {
3077 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:043078 // Negotiate and NTLM are often requested together. However, we only want
3079 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3080 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:293081 MockRead("WWW-Authenticate: NTLM\r\n"),
3082 MockRead("Connection: close\r\n"),
3083 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363084 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293085 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:063086 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293087 };
3088
3089 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:223090 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293091 // request we should be issuing -- the final header line contains a Type
3092 // 1 message.
3093 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3094 "Host: 172.22.68.17\r\n"
3095 "Connection: keep-alive\r\n"
3096 "Authorization: NTLM "
3097 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3098
3099 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3100 // (the credentials for the origin server). The second request continues
3101 // on the same connection.
3102 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3103 "Host: 172.22.68.17\r\n"
3104 "Connection: keep-alive\r\n"
3105 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3106 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3107 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
3108 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
3109 "4Ww7b7E=\r\n\r\n"),
3110 };
3111
3112 MockRead data_reads2[] = {
3113 // The origin server responds with a Type 2 message.
3114 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3115 MockRead("WWW-Authenticate: NTLM "
3116 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
3117 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3118 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3119 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3120 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3121 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3122 "BtAAAAAAA=\r\n"),
3123 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363124 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293125 MockRead("You are not authorized to view this page\r\n"),
3126
3127 // Wrong password.
3128 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:293129 MockRead("WWW-Authenticate: NTLM\r\n"),
3130 MockRead("Connection: close\r\n"),
3131 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363132 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293133 // Missing content -- won't matter, as connection will be reset.
[email protected]8ddf8322012-02-23 18:08:063134 MockRead(SYNCHRONOUS, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293135 };
3136
3137 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223138 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293139 // request we should be issuing -- the final header line contains a Type
3140 // 1 message.
3141 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3142 "Host: 172.22.68.17\r\n"
3143 "Connection: keep-alive\r\n"
3144 "Authorization: NTLM "
3145 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3146
3147 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3148 // (the credentials for the origin server). The second request continues
3149 // on the same connection.
3150 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3151 "Host: 172.22.68.17\r\n"
3152 "Connection: keep-alive\r\n"
3153 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3154 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3155 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3156 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3157 "+4MUm7c=\r\n\r\n"),
3158 };
3159
3160 MockRead data_reads3[] = {
3161 // The origin server responds with a Type 2 message.
3162 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3163 MockRead("WWW-Authenticate: NTLM "
3164 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3165 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3166 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3167 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3168 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3169 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3170 "BtAAAAAAA=\r\n"),
3171 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363172 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293173 MockRead("You are not authorized to view this page\r\n"),
3174
3175 // Lastly we get the desired content.
3176 MockRead("HTTP/1.1 200 OK\r\n"),
3177 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3178 MockRead("Content-Length: 13\r\n\r\n"),
3179 MockRead("Please Login\r\n"),
[email protected]8ddf8322012-02-23 18:08:063180 MockRead(SYNCHRONOUS, OK),
[email protected]385a4672009-03-11 22:21:293181 };
3182
[email protected]31a2bfe2010-02-09 08:03:393183 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3184 data_writes1, arraysize(data_writes1));
3185 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3186 data_writes2, arraysize(data_writes2));
3187 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3188 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593189 session_deps.socket_factory.AddSocketDataProvider(&data1);
3190 session_deps.socket_factory.AddSocketDataProvider(&data2);
3191 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293192
[email protected]49639fa2011-12-20 23:22:413193 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:293194
[email protected]0b0bf032010-09-21 18:08:503195 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3196
[email protected]49639fa2011-12-20 23:22:413197 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423198 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293199
3200 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423201 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293202
[email protected]0757e7702009-03-27 04:00:223203 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293204
[email protected]1c773ea12009-04-28 19:58:423205 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503206 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043207 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:293208
[email protected]49639fa2011-12-20 23:22:413209 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293210
[email protected]0757e7702009-03-27 04:00:223211 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:583212 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:413213 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423214 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293215
[email protected]10af5fe72011-01-31 16:17:253216 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423217 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293218
[email protected]0757e7702009-03-27 04:00:223219 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:413220 TestCompletionCallback callback3;
3221 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423222 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253223 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423224 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223225 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3226
3227 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043228 ASSERT_FALSE(response == NULL);
3229 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:223230
[email protected]49639fa2011-12-20 23:22:413231 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223232
3233 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:583234 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413235 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:253236 EXPECT_EQ(ERR_IO_PENDING, rv);
3237
3238 rv = callback4.WaitForResult();
3239 EXPECT_EQ(OK, rv);
3240
3241 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3242
[email protected]49639fa2011-12-20 23:22:413243 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:253244
3245 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:413246 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:423247 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223248
3249 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423250 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223251
[email protected]385a4672009-03-11 22:21:293252 response = trans->GetResponseInfo();
3253 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3254 EXPECT_EQ(13, response->headers->GetContentLength());
3255}
[email protected]ea9dc9a2009-09-05 00:43:323256#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293257
[email protected]4ddaf2502008-10-23 18:26:193258// Test reading a server response which has only headers, and no body.
3259// After some maximum number of bytes is consumed, the transaction should
3260// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3261TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423262 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193263 request.method = "GET";
3264 request.url = GURL("http://www.google.com/");
3265 request.load_flags = 0;
3266
[email protected]cb9bf6ca2011-01-28 13:15:273267 SessionDependencies session_deps;
3268 scoped_ptr<HttpTransaction> trans(
3269 new HttpNetworkTransaction(CreateSession(&session_deps)));
3270
[email protected]b75b7b2f2009-10-06 00:54:533271 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433272 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533273 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193274
3275 MockRead data_reads[] = {
3276 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:063277 MockRead(ASYNC, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193278 MockRead("\r\nBODY"),
[email protected]8ddf8322012-02-23 18:08:063279 MockRead(SYNCHRONOUS, OK),
[email protected]4ddaf2502008-10-23 18:26:193280 };
[email protected]31a2bfe2010-02-09 08:03:393281 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593282 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193283
[email protected]49639fa2011-12-20 23:22:413284 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:193285
[email protected]49639fa2011-12-20 23:22:413286 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423287 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193288
3289 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423290 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193291
[email protected]1c773ea12009-04-28 19:58:423292 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193293 EXPECT_TRUE(response == NULL);
3294}
[email protected]f4e426b2008-11-05 00:24:493295
3296// Make sure that we don't try to reuse a TCPClientSocket when failing to
3297// establish tunnel.
3298// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283299TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273300 HttpRequestInfo request;
3301 request.method = "GET";
3302 request.url = GURL("https://www.google.com/");
3303 request.load_flags = 0;
3304
[email protected]f4e426b2008-11-05 00:24:493305 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003306 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013307
[email protected]228ff742009-06-05 01:19:593308 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493309
[email protected]5695b8c2009-09-30 21:36:433310 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493311
[email protected]f4e426b2008-11-05 00:24:493312 // Since we have proxy, should try to establish tunnel.
3313 MockWrite data_writes1[] = {
3314 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453315 "Host: www.google.com\r\n"
3316 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493317 };
3318
[email protected]77848d12008-11-14 00:00:223319 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493320 // connection. Usually a proxy would return 501 (not implemented),
3321 // or 200 (tunnel established).
3322 MockRead data_reads1[] = {
3323 MockRead("HTTP/1.1 404 Not Found\r\n"),
3324 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063325 MockRead(SYNCHRONOUS, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493326 };
3327
[email protected]31a2bfe2010-02-09 08:03:393328 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3329 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593330 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493331
[email protected]49639fa2011-12-20 23:22:413332 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:493333
[email protected]49639fa2011-12-20 23:22:413334 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423335 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493336
3337 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423338 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493339
[email protected]1c773ea12009-04-28 19:58:423340 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083341 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493342
[email protected]b4404c02009-04-10 16:38:523343 // Empty the current queue. This is necessary because idle sockets are
3344 // added to the connection pool asynchronously with a PostTask.
3345 MessageLoop::current()->RunAllPending();
3346
[email protected]f4e426b2008-11-05 00:24:493347 // We now check to make sure the TCPClientSocket was not added back to
3348 // the pool.
[email protected]a42dbd142011-11-17 16:42:023349 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493350 trans.reset();
[email protected]b4404c02009-04-10 16:38:523351 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493352 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a42dbd142011-11-17 16:42:023353 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493354}
[email protected]372d34a2008-11-05 21:30:513355
[email protected]1b157c02009-04-21 01:55:403356// Make sure that we recycle a socket after reading all of the response body.
3357TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423358 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403359 request.method = "GET";
3360 request.url = GURL("http://www.google.com/");
3361 request.load_flags = 0;
3362
[email protected]cb9bf6ca2011-01-28 13:15:273363 SessionDependencies session_deps;
3364 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3365
3366 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3367
[email protected]1b157c02009-04-21 01:55:403368 MockRead data_reads[] = {
3369 // A part of the response body is received with the response headers.
3370 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3371 // The rest of the response body is received in two parts.
3372 MockRead("lo"),
3373 MockRead(" world"),
3374 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:063375 MockRead(SYNCHRONOUS, OK),
[email protected]1b157c02009-04-21 01:55:403376 };
3377
[email protected]31a2bfe2010-02-09 08:03:393378 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593379 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403380
[email protected]49639fa2011-12-20 23:22:413381 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:403382
[email protected]49639fa2011-12-20 23:22:413383 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423384 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403385
3386 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423387 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403388
[email protected]1c773ea12009-04-28 19:58:423389 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503390 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:403391
3392 EXPECT_TRUE(response->headers != NULL);
3393 std::string status_line = response->headers->GetStatusLine();
3394 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3395
[email protected]a42dbd142011-11-17 16:42:023396 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403397
3398 std::string response_data;
3399 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423400 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403401 EXPECT_EQ("hello world", response_data);
3402
3403 // Empty the current queue. This is necessary because idle sockets are
3404 // added to the connection pool asynchronously with a PostTask.
3405 MessageLoop::current()->RunAllPending();
3406
3407 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023408 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403409}
3410
[email protected]76a505b2010-08-25 06:23:003411// Make sure that we recycle a SSL socket after reading all of the response
3412// body.
3413TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3414 SessionDependencies session_deps;
3415 HttpRequestInfo request;
3416 request.method = "GET";
3417 request.url = GURL("https://www.google.com/");
3418 request.load_flags = 0;
3419
3420 MockWrite data_writes[] = {
3421 MockWrite("GET / HTTP/1.1\r\n"
3422 "Host: www.google.com\r\n"
3423 "Connection: keep-alive\r\n\r\n"),
3424 };
3425
3426 MockRead data_reads[] = {
3427 MockRead("HTTP/1.1 200 OK\r\n"),
3428 MockRead("Content-Length: 11\r\n\r\n"),
3429 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:063430 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:003431 };
3432
[email protected]8ddf8322012-02-23 18:08:063433 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]76a505b2010-08-25 06:23:003434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3435
3436 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3437 data_writes, arraysize(data_writes));
3438 session_deps.socket_factory.AddSocketDataProvider(&data);
3439
[email protected]49639fa2011-12-20 23:22:413440 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003441
3442 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3443 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3444
[email protected]49639fa2011-12-20 23:22:413445 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003446
3447 EXPECT_EQ(ERR_IO_PENDING, rv);
3448 EXPECT_EQ(OK, callback.WaitForResult());
3449
3450 const HttpResponseInfo* response = trans->GetResponseInfo();
3451 ASSERT_TRUE(response != NULL);
3452 ASSERT_TRUE(response->headers != NULL);
3453 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3454
[email protected]a42dbd142011-11-17 16:42:023455 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003456
3457 std::string response_data;
3458 rv = ReadTransaction(trans.get(), &response_data);
3459 EXPECT_EQ(OK, rv);
3460 EXPECT_EQ("hello world", response_data);
3461
3462 // Empty the current queue. This is necessary because idle sockets are
3463 // added to the connection pool asynchronously with a PostTask.
3464 MessageLoop::current()->RunAllPending();
3465
3466 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023467 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003468}
3469
3470// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3471// from the pool and make sure that we recover okay.
3472TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3473 SessionDependencies session_deps;
3474 HttpRequestInfo request;
3475 request.method = "GET";
3476 request.url = GURL("https://www.google.com/");
3477 request.load_flags = 0;
3478
3479 MockWrite data_writes[] = {
3480 MockWrite("GET / HTTP/1.1\r\n"
3481 "Host: www.google.com\r\n"
3482 "Connection: keep-alive\r\n\r\n"),
3483 MockWrite("GET / HTTP/1.1\r\n"
3484 "Host: www.google.com\r\n"
3485 "Connection: keep-alive\r\n\r\n"),
3486 };
3487
3488 MockRead data_reads[] = {
3489 MockRead("HTTP/1.1 200 OK\r\n"),
3490 MockRead("Content-Length: 11\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063491 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:003492 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:063493 MockRead(ASYNC, 0, 0) // EOF
[email protected]76a505b2010-08-25 06:23:003494 };
3495
[email protected]8ddf8322012-02-23 18:08:063496 SSLSocketDataProvider ssl(ASYNC, OK);
3497 SSLSocketDataProvider ssl2(ASYNC, OK);
[email protected]76a505b2010-08-25 06:23:003498 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3499 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3500
3501 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3502 data_writes, arraysize(data_writes));
3503 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3504 data_writes, arraysize(data_writes));
3505 session_deps.socket_factory.AddSocketDataProvider(&data);
3506 session_deps.socket_factory.AddSocketDataProvider(&data2);
3507
[email protected]49639fa2011-12-20 23:22:413508 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003509
3510 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3511 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3512
[email protected]49639fa2011-12-20 23:22:413513 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003514
3515 EXPECT_EQ(ERR_IO_PENDING, rv);
3516 EXPECT_EQ(OK, callback.WaitForResult());
3517
3518 const HttpResponseInfo* response = trans->GetResponseInfo();
3519 ASSERT_TRUE(response != NULL);
3520 ASSERT_TRUE(response->headers != NULL);
3521 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3522
[email protected]a42dbd142011-11-17 16:42:023523 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003524
3525 std::string response_data;
3526 rv = ReadTransaction(trans.get(), &response_data);
3527 EXPECT_EQ(OK, rv);
3528 EXPECT_EQ("hello world", response_data);
3529
3530 // Empty the current queue. This is necessary because idle sockets are
3531 // added to the connection pool asynchronously with a PostTask.
3532 MessageLoop::current()->RunAllPending();
3533
3534 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023535 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003536
3537 // Now start the second transaction, which should reuse the previous socket.
3538
3539 trans.reset(new HttpNetworkTransaction(session));
3540
[email protected]49639fa2011-12-20 23:22:413541 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003542
3543 EXPECT_EQ(ERR_IO_PENDING, rv);
3544 EXPECT_EQ(OK, callback.WaitForResult());
3545
3546 response = trans->GetResponseInfo();
3547 ASSERT_TRUE(response != NULL);
3548 ASSERT_TRUE(response->headers != NULL);
3549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3550
[email protected]a42dbd142011-11-17 16:42:023551 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003552
3553 rv = ReadTransaction(trans.get(), &response_data);
3554 EXPECT_EQ(OK, rv);
3555 EXPECT_EQ("hello world", response_data);
3556
3557 // Empty the current queue. This is necessary because idle sockets are
3558 // added to the connection pool asynchronously with a PostTask.
3559 MessageLoop::current()->RunAllPending();
3560
3561 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023562 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003563}
3564
[email protected]b4404c02009-04-10 16:38:523565// Make sure that we recycle a socket after a zero-length response.
3566// http://crbug.com/9880
3567TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423568 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523569 request.method = "GET";
3570 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3571 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3572 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3573 "rt=prt.2642,ol.2649,xjs.2951");
3574 request.load_flags = 0;
3575
[email protected]cb9bf6ca2011-01-28 13:15:273576 SessionDependencies session_deps;
3577 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3578
3579 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3580
[email protected]b4404c02009-04-10 16:38:523581 MockRead data_reads[] = {
3582 MockRead("HTTP/1.1 204 No Content\r\n"
3583 "Content-Length: 0\r\n"
3584 "Content-Type: text/html\r\n\r\n"),
3585 MockRead("junk"), // Should not be read!!
[email protected]8ddf8322012-02-23 18:08:063586 MockRead(SYNCHRONOUS, OK),
[email protected]b4404c02009-04-10 16:38:523587 };
3588
[email protected]31a2bfe2010-02-09 08:03:393589 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593590 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523591
[email protected]49639fa2011-12-20 23:22:413592 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:523593
[email protected]49639fa2011-12-20 23:22:413594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423595 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523596
3597 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423598 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523599
[email protected]1c773ea12009-04-28 19:58:423600 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503601 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:523602
3603 EXPECT_TRUE(response->headers != NULL);
3604 std::string status_line = response->headers->GetStatusLine();
3605 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3606
[email protected]a42dbd142011-11-17 16:42:023607 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523608
3609 std::string response_data;
3610 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423611 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523612 EXPECT_EQ("", response_data);
3613
3614 // Empty the current queue. This is necessary because idle sockets are
3615 // added to the connection pool asynchronously with a PostTask.
3616 MessageLoop::current()->RunAllPending();
3617
3618 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023619 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523620}
3621
[email protected]372d34a2008-11-05 21:30:513622TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423623 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513624 // Transaction 1: a GET request that succeeds. The socket is recycled
3625 // after use.
3626 request[0].method = "GET";
3627 request[0].url = GURL("http://www.google.com/");
3628 request[0].load_flags = 0;
3629 // Transaction 2: a POST request. Reuses the socket kept alive from
3630 // transaction 1. The first attempts fails when writing the POST data.
3631 // This causes the transaction to retry with a new socket. The second
3632 // attempt succeeds.
3633 request[1].method = "POST";
3634 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423635 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513636 request[1].upload_data->AppendBytes("foo", 3);
3637 request[1].load_flags = 0;
3638
[email protected]228ff742009-06-05 01:19:593639 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273640 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513641
3642 // The first socket is used for transaction 1 and the first attempt of
3643 // transaction 2.
3644
3645 // The response of transaction 1.
3646 MockRead data_reads1[] = {
3647 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3648 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:063649 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:513650 };
3651 // The mock write results of transaction 1 and the first attempt of
3652 // transaction 2.
3653 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:063654 MockWrite(SYNCHRONOUS, 64), // GET
3655 MockWrite(SYNCHRONOUS, 93), // POST
3656 MockWrite(SYNCHRONOUS, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513657 };
[email protected]31a2bfe2010-02-09 08:03:393658 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3659 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513660
3661 // The second socket is used for the second attempt of transaction 2.
3662
3663 // The response of transaction 2.
3664 MockRead data_reads2[] = {
3665 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3666 MockRead("welcome"),
[email protected]8ddf8322012-02-23 18:08:063667 MockRead(SYNCHRONOUS, OK),
[email protected]372d34a2008-11-05 21:30:513668 };
3669 // The mock write results of the second attempt of transaction 2.
3670 MockWrite data_writes2[] = {
[email protected]8ddf8322012-02-23 18:08:063671 MockWrite(SYNCHRONOUS, 93), // POST
3672 MockWrite(SYNCHRONOUS, 3), // POST data
[email protected]372d34a2008-11-05 21:30:513673 };
[email protected]31a2bfe2010-02-09 08:03:393674 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3675 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513676
[email protected]5ecc992a42009-11-11 01:41:593677 session_deps.socket_factory.AddSocketDataProvider(&data1);
3678 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513679
3680 const char* kExpectedResponseData[] = {
3681 "hello world", "welcome"
3682 };
3683
3684 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423685 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433686 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513687
[email protected]49639fa2011-12-20 23:22:413688 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:513689
[email protected]49639fa2011-12-20 23:22:413690 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423691 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513692
3693 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423694 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513695
[email protected]1c773ea12009-04-28 19:58:423696 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503697 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:513698
3699 EXPECT_TRUE(response->headers != NULL);
3700 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3701
3702 std::string response_data;
3703 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423704 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513705 EXPECT_EQ(kExpectedResponseData[i], response_data);
3706 }
3707}
[email protected]f9ee6b52008-11-08 06:46:233708
3709// Test the request-challenge-retry sequence for basic auth when there is
3710// an identity in the URL. The request should be sent as normal, but when
[email protected]7b08ba62012-02-10 20:19:413711// it fails the identity from the URL is no longer used.
3712TEST_F(HttpNetworkTransactionTest, IgnoreAuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423713 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233714 request.method = "GET";
[email protected]a97cca42009-08-14 01:00:293715 request.url = GURL("http://foo:b@[email protected]/");
[email protected]7b08ba62012-02-10 20:19:413716 request.load_flags = LOAD_NORMAL;
[email protected]a97cca42009-08-14 01:00:293717
[email protected]cb9bf6ca2011-01-28 13:15:273718 SessionDependencies session_deps;
3719 scoped_ptr<HttpTransaction> trans(
3720 new HttpNetworkTransaction(CreateSession(&session_deps)));
3721
[email protected]a97cca42009-08-14 01:00:293722 // The password contains an escaped character -- for this test to pass it
3723 // will need to be unescaped by HttpNetworkTransaction.
3724 EXPECT_EQ("b%40r", request.url.password());
3725
[email protected]f9ee6b52008-11-08 06:46:233726 MockWrite data_writes1[] = {
3727 MockWrite("GET / HTTP/1.1\r\n"
3728 "Host: www.google.com\r\n"
3729 "Connection: keep-alive\r\n\r\n"),
3730 };
3731
3732 MockRead data_reads1[] = {
3733 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3734 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3735 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063736 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233737 };
3738
[email protected]31a2bfe2010-02-09 08:03:393739 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3740 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593741 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233742
[email protected]49639fa2011-12-20 23:22:413743 TestCompletionCallback callback1;
[email protected]49639fa2011-12-20 23:22:413744 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423745 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233746 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423747 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223748 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3749
[email protected]ea9dc9a2009-09-05 00:43:323750 // Empty the current queue.
3751 MessageLoop::current()->RunAllPending();
3752}
3753
[email protected]f9ee6b52008-11-08 06:46:233754// Test that previously tried username/passwords for a realm get re-used.
3755TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593756 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233758
3759 // Transaction 1: authenticate (foo, bar) on MyRealm1
3760 {
[email protected]1c773ea12009-04-28 19:58:423761 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233762 request.method = "GET";
3763 request.url = GURL("http://www.google.com/x/y/z");
3764 request.load_flags = 0;
3765
[email protected]cb9bf6ca2011-01-28 13:15:273766 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3767
[email protected]f9ee6b52008-11-08 06:46:233768 MockWrite data_writes1[] = {
3769 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3770 "Host: www.google.com\r\n"
3771 "Connection: keep-alive\r\n\r\n"),
3772 };
3773
3774 MockRead data_reads1[] = {
3775 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3776 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3777 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063778 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233779 };
3780
3781 // Resend with authorization (username=foo, password=bar)
3782 MockWrite data_writes2[] = {
3783 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3784 "Host: www.google.com\r\n"
3785 "Connection: keep-alive\r\n"
3786 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3787 };
3788
3789 // Sever accepts the authorization.
3790 MockRead data_reads2[] = {
3791 MockRead("HTTP/1.0 200 OK\r\n"),
3792 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063793 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:233794 };
3795
[email protected]31a2bfe2010-02-09 08:03:393796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3797 data_writes1, arraysize(data_writes1));
3798 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3799 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593800 session_deps.socket_factory.AddSocketDataProvider(&data1);
3801 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233802
[email protected]49639fa2011-12-20 23:22:413803 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233804
[email protected]49639fa2011-12-20 23:22:413805 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423806 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233807
3808 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423809 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233810
[email protected]1c773ea12009-04-28 19:58:423811 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503812 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043813 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:233814
[email protected]49639fa2011-12-20 23:22:413815 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233816
[email protected]49639fa2011-12-20 23:22:413817 rv = trans->RestartWithAuth(
3818 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423819 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233820
3821 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423822 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233823
3824 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503825 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233826 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3827 EXPECT_EQ(100, response->headers->GetContentLength());
3828 }
3829
3830 // ------------------------------------------------------------------------
3831
3832 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3833 {
[email protected]1c773ea12009-04-28 19:58:423834 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233835 request.method = "GET";
3836 // Note that Transaction 1 was at /x/y/z, so this is in the same
3837 // protection space as MyRealm1.
3838 request.url = GURL("http://www.google.com/x/y/a/b");
3839 request.load_flags = 0;
3840
[email protected]cb9bf6ca2011-01-28 13:15:273841 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3842
[email protected]f9ee6b52008-11-08 06:46:233843 MockWrite data_writes1[] = {
3844 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3845 "Host: www.google.com\r\n"
3846 "Connection: keep-alive\r\n"
3847 // Send preemptive authorization for MyRealm1
3848 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3849 };
3850
3851 // The server didn't like the preemptive authorization, and
3852 // challenges us for a different realm (MyRealm2).
3853 MockRead data_reads1[] = {
3854 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3855 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3856 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063857 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233858 };
3859
3860 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3861 MockWrite data_writes2[] = {
3862 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3863 "Host: www.google.com\r\n"
3864 "Connection: keep-alive\r\n"
3865 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3866 };
3867
3868 // Sever accepts the authorization.
3869 MockRead data_reads2[] = {
3870 MockRead("HTTP/1.0 200 OK\r\n"),
3871 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063872 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:233873 };
3874
[email protected]31a2bfe2010-02-09 08:03:393875 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3876 data_writes1, arraysize(data_writes1));
3877 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3878 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593879 session_deps.socket_factory.AddSocketDataProvider(&data1);
3880 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233881
[email protected]49639fa2011-12-20 23:22:413882 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233883
[email protected]49639fa2011-12-20 23:22:413884 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423885 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233886
3887 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423888 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233889
[email protected]1c773ea12009-04-28 19:58:423890 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503891 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043892 ASSERT_TRUE(response->auth_challenge.get());
3893 EXPECT_FALSE(response->auth_challenge->is_proxy);
3894 EXPECT_EQ("www.google.com:80",
3895 response->auth_challenge->challenger.ToString());
3896 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
3897 EXPECT_EQ("basic", response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:233898
[email protected]49639fa2011-12-20 23:22:413899 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233900
[email protected]49639fa2011-12-20 23:22:413901 rv = trans->RestartWithAuth(
3902 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423903 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233904
3905 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423906 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233907
3908 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503909 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233910 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3911 EXPECT_EQ(100, response->headers->GetContentLength());
3912 }
3913
3914 // ------------------------------------------------------------------------
3915
3916 // Transaction 3: Resend a request in MyRealm's protection space --
3917 // succeed with preemptive authorization.
3918 {
[email protected]1c773ea12009-04-28 19:58:423919 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233920 request.method = "GET";
3921 request.url = GURL("http://www.google.com/x/y/z2");
3922 request.load_flags = 0;
3923
[email protected]cb9bf6ca2011-01-28 13:15:273924 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3925
[email protected]f9ee6b52008-11-08 06:46:233926 MockWrite data_writes1[] = {
3927 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3928 "Host: www.google.com\r\n"
3929 "Connection: keep-alive\r\n"
3930 // The authorization for MyRealm1 gets sent preemptively
3931 // (since the url is in the same protection space)
3932 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3933 };
3934
3935 // Sever accepts the preemptive authorization
3936 MockRead data_reads1[] = {
3937 MockRead("HTTP/1.0 200 OK\r\n"),
3938 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063939 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:233940 };
3941
[email protected]31a2bfe2010-02-09 08:03:393942 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3943 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593944 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233945
[email protected]49639fa2011-12-20 23:22:413946 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233947
[email protected]49639fa2011-12-20 23:22:413948 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423949 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233950
3951 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423952 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233953
[email protected]1c773ea12009-04-28 19:58:423954 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503955 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233956
3957 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3958 EXPECT_EQ(100, response->headers->GetContentLength());
3959 }
3960
3961 // ------------------------------------------------------------------------
3962
3963 // Transaction 4: request another URL in MyRealm (however the
3964 // url is not known to belong to the protection space, so no pre-auth).
3965 {
[email protected]1c773ea12009-04-28 19:58:423966 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233967 request.method = "GET";
3968 request.url = GURL("http://www.google.com/x/1");
3969 request.load_flags = 0;
3970
[email protected]cb9bf6ca2011-01-28 13:15:273971 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3972
[email protected]f9ee6b52008-11-08 06:46:233973 MockWrite data_writes1[] = {
3974 MockWrite("GET /x/1 HTTP/1.1\r\n"
3975 "Host: www.google.com\r\n"
3976 "Connection: keep-alive\r\n\r\n"),
3977 };
3978
3979 MockRead data_reads1[] = {
3980 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3981 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3982 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063983 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233984 };
3985
3986 // Resend with authorization from MyRealm's cache.
3987 MockWrite data_writes2[] = {
3988 MockWrite("GET /x/1 HTTP/1.1\r\n"
3989 "Host: www.google.com\r\n"
3990 "Connection: keep-alive\r\n"
3991 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3992 };
3993
3994 // Sever accepts the authorization.
3995 MockRead data_reads2[] = {
3996 MockRead("HTTP/1.0 200 OK\r\n"),
3997 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:063998 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:233999 };
4000
[email protected]31a2bfe2010-02-09 08:03:394001 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4002 data_writes1, arraysize(data_writes1));
4003 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4004 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594005 session_deps.socket_factory.AddSocketDataProvider(&data1);
4006 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234007
[email protected]49639fa2011-12-20 23:22:414008 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234009
[email protected]49639fa2011-12-20 23:22:414010 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424011 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234012
4013 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424014 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234015
[email protected]0757e7702009-03-27 04:00:224016 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414017 TestCompletionCallback callback2;
4018 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424019 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224020 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424021 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224022 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4023
[email protected]1c773ea12009-04-28 19:58:424024 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504025 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234026 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4027 EXPECT_EQ(100, response->headers->GetContentLength());
4028 }
4029
4030 // ------------------------------------------------------------------------
4031
4032 // Transaction 5: request a URL in MyRealm, but the server rejects the
4033 // cached identity. Should invalidate and re-prompt.
4034 {
[email protected]1c773ea12009-04-28 19:58:424035 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234036 request.method = "GET";
4037 request.url = GURL("http://www.google.com/p/q/t");
4038 request.load_flags = 0;
4039
[email protected]cb9bf6ca2011-01-28 13:15:274040 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4041
[email protected]f9ee6b52008-11-08 06:46:234042 MockWrite data_writes1[] = {
4043 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4044 "Host: www.google.com\r\n"
4045 "Connection: keep-alive\r\n\r\n"),
4046 };
4047
4048 MockRead data_reads1[] = {
4049 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4050 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4051 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064052 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234053 };
4054
4055 // Resend with authorization from cache for MyRealm.
4056 MockWrite data_writes2[] = {
4057 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4058 "Host: www.google.com\r\n"
4059 "Connection: keep-alive\r\n"
4060 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4061 };
4062
4063 // Sever rejects the authorization.
4064 MockRead data_reads2[] = {
4065 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4066 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4067 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064068 MockRead(SYNCHRONOUS, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234069 };
4070
4071 // At this point we should prompt for new credentials for MyRealm.
4072 // Restart with username=foo3, password=foo4.
4073 MockWrite data_writes3[] = {
4074 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4075 "Host: www.google.com\r\n"
4076 "Connection: keep-alive\r\n"
4077 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4078 };
4079
4080 // Sever accepts the authorization.
4081 MockRead data_reads3[] = {
4082 MockRead("HTTP/1.0 200 OK\r\n"),
4083 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064084 MockRead(SYNCHRONOUS, OK),
[email protected]f9ee6b52008-11-08 06:46:234085 };
4086
[email protected]31a2bfe2010-02-09 08:03:394087 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4088 data_writes1, arraysize(data_writes1));
4089 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4090 data_writes2, arraysize(data_writes2));
4091 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4092 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594093 session_deps.socket_factory.AddSocketDataProvider(&data1);
4094 session_deps.socket_factory.AddSocketDataProvider(&data2);
4095 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234096
[email protected]49639fa2011-12-20 23:22:414097 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234098
[email protected]49639fa2011-12-20 23:22:414099 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424100 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234101
4102 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424103 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234104
[email protected]0757e7702009-03-27 04:00:224105 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414106 TestCompletionCallback callback2;
4107 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424108 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224109 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424110 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224111 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4112
[email protected]1c773ea12009-04-28 19:58:424113 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504114 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044115 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:234116
[email protected]49639fa2011-12-20 23:22:414117 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234118
[email protected]49639fa2011-12-20 23:22:414119 rv = trans->RestartWithAuth(
4120 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:424121 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234122
[email protected]0757e7702009-03-27 04:00:224123 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424124 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234125
4126 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504127 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234128 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4129 EXPECT_EQ(100, response->headers->GetContentLength());
4130 }
4131}
[email protected]89ceba9a2009-03-21 03:46:064132
[email protected]3c32c5f2010-05-18 15:18:124133// Tests that nonce count increments when multiple auth attempts
4134// are started with the same nonce.
4135TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4136 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444137 HttpAuthHandlerDigest::Factory* digest_factory =
4138 new HttpAuthHandlerDigest::Factory();
4139 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4140 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4141 digest_factory->set_nonce_generator(nonce_generator);
4142 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274143 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124144
4145 // Transaction 1: authenticate (foo, bar) on MyRealm1
4146 {
[email protected]3c32c5f2010-05-18 15:18:124147 HttpRequestInfo request;
4148 request.method = "GET";
4149 request.url = GURL("http://www.google.com/x/y/z");
4150 request.load_flags = 0;
4151
[email protected]cb9bf6ca2011-01-28 13:15:274152 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4153
[email protected]3c32c5f2010-05-18 15:18:124154 MockWrite data_writes1[] = {
4155 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4156 "Host: www.google.com\r\n"
4157 "Connection: keep-alive\r\n\r\n"),
4158 };
4159
4160 MockRead data_reads1[] = {
4161 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4162 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4163 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064164 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:124165 };
4166
4167 // Resend with authorization (username=foo, password=bar)
4168 MockWrite data_writes2[] = {
4169 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4170 "Host: www.google.com\r\n"
4171 "Connection: keep-alive\r\n"
4172 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4173 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4174 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4175 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4176 };
4177
4178 // Sever accepts the authorization.
4179 MockRead data_reads2[] = {
4180 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]8ddf8322012-02-23 18:08:064181 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:124182 };
4183
4184 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4185 data_writes1, arraysize(data_writes1));
4186 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4187 data_writes2, arraysize(data_writes2));
4188 session_deps.socket_factory.AddSocketDataProvider(&data1);
4189 session_deps.socket_factory.AddSocketDataProvider(&data2);
4190
[email protected]49639fa2011-12-20 23:22:414191 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124192
[email protected]49639fa2011-12-20 23:22:414193 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124194 EXPECT_EQ(ERR_IO_PENDING, rv);
4195
4196 rv = callback1.WaitForResult();
4197 EXPECT_EQ(OK, rv);
4198
4199 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504200 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044201 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:124202
[email protected]49639fa2011-12-20 23:22:414203 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:124204
[email protected]49639fa2011-12-20 23:22:414205 rv = trans->RestartWithAuth(
4206 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:124207 EXPECT_EQ(ERR_IO_PENDING, rv);
4208
4209 rv = callback2.WaitForResult();
4210 EXPECT_EQ(OK, rv);
4211
4212 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504213 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124214 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4215 }
4216
4217 // ------------------------------------------------------------------------
4218
4219 // Transaction 2: Request another resource in digestive's protection space.
4220 // This will preemptively add an Authorization header which should have an
4221 // "nc" value of 2 (as compared to 1 in the first use.
4222 {
[email protected]3c32c5f2010-05-18 15:18:124223 HttpRequestInfo request;
4224 request.method = "GET";
4225 // Note that Transaction 1 was at /x/y/z, so this is in the same
4226 // protection space as digest.
4227 request.url = GURL("http://www.google.com/x/y/a/b");
4228 request.load_flags = 0;
4229
[email protected]cb9bf6ca2011-01-28 13:15:274230 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4231
[email protected]3c32c5f2010-05-18 15:18:124232 MockWrite data_writes1[] = {
4233 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4234 "Host: www.google.com\r\n"
4235 "Connection: keep-alive\r\n"
4236 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4237 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4238 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4239 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4240 };
4241
4242 // Sever accepts the authorization.
4243 MockRead data_reads1[] = {
4244 MockRead("HTTP/1.0 200 OK\r\n"),
4245 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064246 MockRead(SYNCHRONOUS, OK),
[email protected]3c32c5f2010-05-18 15:18:124247 };
4248
4249 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4250 data_writes1, arraysize(data_writes1));
4251 session_deps.socket_factory.AddSocketDataProvider(&data1);
4252
[email protected]49639fa2011-12-20 23:22:414253 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124254
[email protected]49639fa2011-12-20 23:22:414255 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124256 EXPECT_EQ(ERR_IO_PENDING, rv);
4257
4258 rv = callback1.WaitForResult();
4259 EXPECT_EQ(OK, rv);
4260
4261 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504262 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124263 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4264 }
4265}
4266
[email protected]89ceba9a2009-03-21 03:46:064267// Test the ResetStateForRestart() private method.
4268TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4269 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594270 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404271 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434272 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064273
4274 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064275 trans->read_buf_ = new IOBuffer(15);
4276 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204277 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064278
4279 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144280 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574281 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:084282 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:574283 response->response_time = base::Time::Now();
4284 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064285
4286 { // Setup state for response_.vary_data
4287 HttpRequestInfo request;
4288 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4289 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274290 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434291 request.extra_headers.SetHeader("Foo", "1");
4292 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574293 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064294 }
4295
4296 // Cause the above state to be reset.
4297 trans->ResetStateForRestart();
4298
4299 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074300 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064301 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204302 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574303 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4304 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044305 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:084306 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:574307 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064308}
4309
[email protected]bacff652009-03-31 17:50:334310// Test HTTPS connections to a site with a bad certificate
4311TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334312 HttpRequestInfo request;
4313 request.method = "GET";
4314 request.url = GURL("https://www.google.com/");
4315 request.load_flags = 0;
4316
[email protected]cb9bf6ca2011-01-28 13:15:274317 SessionDependencies session_deps;
4318 scoped_ptr<HttpTransaction> trans(
4319 new HttpNetworkTransaction(CreateSession(&session_deps)));
4320
[email protected]bacff652009-03-31 17:50:334321 MockWrite data_writes[] = {
4322 MockWrite("GET / HTTP/1.1\r\n"
4323 "Host: www.google.com\r\n"
4324 "Connection: keep-alive\r\n\r\n"),
4325 };
4326
4327 MockRead data_reads[] = {
4328 MockRead("HTTP/1.0 200 OK\r\n"),
4329 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4330 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064331 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:334332 };
4333
[email protected]5ecc992a42009-11-11 01:41:594334 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394335 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4336 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:064337 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
4338 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:334339
[email protected]5ecc992a42009-11-11 01:41:594340 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4341 session_deps.socket_factory.AddSocketDataProvider(&data);
4342 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4343 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334344
[email protected]49639fa2011-12-20 23:22:414345 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334346
[email protected]49639fa2011-12-20 23:22:414347 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334348 EXPECT_EQ(ERR_IO_PENDING, rv);
4349
4350 rv = callback.WaitForResult();
4351 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4352
[email protected]49639fa2011-12-20 23:22:414353 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334354 EXPECT_EQ(ERR_IO_PENDING, rv);
4355
4356 rv = callback.WaitForResult();
4357 EXPECT_EQ(OK, rv);
4358
4359 const HttpResponseInfo* response = trans->GetResponseInfo();
4360
[email protected]fe2255a2011-09-20 19:37:504361 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334362 EXPECT_EQ(100, response->headers->GetContentLength());
4363}
4364
4365// Test HTTPS connections to a site with a bad certificate, going through a
4366// proxy
4367TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004368 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334369
4370 HttpRequestInfo request;
4371 request.method = "GET";
4372 request.url = GURL("https://www.google.com/");
4373 request.load_flags = 0;
4374
4375 MockWrite proxy_writes[] = {
4376 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454377 "Host: www.google.com\r\n"
4378 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334379 };
4380
4381 MockRead proxy_reads[] = {
4382 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064383 MockRead(SYNCHRONOUS, OK)
[email protected]bacff652009-03-31 17:50:334384 };
4385
4386 MockWrite data_writes[] = {
4387 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454388 "Host: www.google.com\r\n"
4389 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334390 MockWrite("GET / HTTP/1.1\r\n"
4391 "Host: www.google.com\r\n"
4392 "Connection: keep-alive\r\n\r\n"),
4393 };
4394
4395 MockRead data_reads[] = {
4396 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4397 MockRead("HTTP/1.0 200 OK\r\n"),
4398 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4399 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064400 MockRead(SYNCHRONOUS, OK),
[email protected]bacff652009-03-31 17:50:334401 };
4402
[email protected]31a2bfe2010-02-09 08:03:394403 StaticSocketDataProvider ssl_bad_certificate(
4404 proxy_reads, arraysize(proxy_reads),
4405 proxy_writes, arraysize(proxy_writes));
4406 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4407 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:064408 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
4409 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]bacff652009-03-31 17:50:334410
[email protected]5ecc992a42009-11-11 01:41:594411 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4412 session_deps.socket_factory.AddSocketDataProvider(&data);
4413 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4414 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334415
[email protected]49639fa2011-12-20 23:22:414416 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334417
4418 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594419 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334420
[email protected]d207a5f2009-06-04 05:28:404421 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434422 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334423
[email protected]49639fa2011-12-20 23:22:414424 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334425 EXPECT_EQ(ERR_IO_PENDING, rv);
4426
4427 rv = callback.WaitForResult();
4428 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4429
[email protected]49639fa2011-12-20 23:22:414430 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334431 EXPECT_EQ(ERR_IO_PENDING, rv);
4432
4433 rv = callback.WaitForResult();
4434 EXPECT_EQ(OK, rv);
4435
4436 const HttpResponseInfo* response = trans->GetResponseInfo();
4437
[email protected]fe2255a2011-09-20 19:37:504438 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334439 EXPECT_EQ(100, response->headers->GetContentLength());
4440 }
4441}
4442
[email protected]2df19bb2010-08-25 20:13:464443
4444// Test HTTPS connections to a site, going through an HTTPS proxy
4445TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114446 SessionDependencies session_deps(ProxyService::CreateFixed(
4447 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464448
4449 HttpRequestInfo request;
4450 request.method = "GET";
4451 request.url = GURL("https://www.google.com/");
4452 request.load_flags = 0;
4453
4454 MockWrite data_writes[] = {
4455 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4456 "Host: www.google.com\r\n"
4457 "Proxy-Connection: keep-alive\r\n\r\n"),
4458 MockWrite("GET / HTTP/1.1\r\n"
4459 "Host: www.google.com\r\n"
4460 "Connection: keep-alive\r\n\r\n"),
4461 };
4462
4463 MockRead data_reads[] = {
4464 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4465 MockRead("HTTP/1.1 200 OK\r\n"),
4466 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4467 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064468 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464469 };
4470
4471 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4472 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:064473 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
4474 SSLSocketDataProvider tunnel_ssl(ASYNC, OK); // SSL through the tunnel
[email protected]2df19bb2010-08-25 20:13:464475
4476 session_deps.socket_factory.AddSocketDataProvider(&data);
4477 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4478 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4479
[email protected]49639fa2011-12-20 23:22:414480 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464481
4482 scoped_ptr<HttpTransaction> trans(
4483 new HttpNetworkTransaction(CreateSession(&session_deps)));
4484
[email protected]49639fa2011-12-20 23:22:414485 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464486 EXPECT_EQ(ERR_IO_PENDING, rv);
4487
4488 rv = callback.WaitForResult();
4489 EXPECT_EQ(OK, rv);
4490 const HttpResponseInfo* response = trans->GetResponseInfo();
4491
[email protected]fe2255a2011-09-20 19:37:504492 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464493
4494 EXPECT_TRUE(response->headers->IsKeepAlive());
4495 EXPECT_EQ(200, response->headers->response_code());
4496 EXPECT_EQ(100, response->headers->GetContentLength());
4497 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4498}
4499
[email protected]511f6f52010-12-17 03:58:294500// Test an HTTPS Proxy's ability to redirect a CONNECT request
4501TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4502 SessionDependencies session_deps(
4503 ProxyService::CreateFixed("https://proxy:70"));
4504
4505 HttpRequestInfo request;
4506 request.method = "GET";
4507 request.url = GURL("https://www.google.com/");
4508 request.load_flags = 0;
4509
4510 MockWrite data_writes[] = {
4511 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4512 "Host: www.google.com\r\n"
4513 "Proxy-Connection: keep-alive\r\n\r\n"),
4514 };
4515
4516 MockRead data_reads[] = {
4517 MockRead("HTTP/1.1 302 Redirect\r\n"),
4518 MockRead("Location: http://login.example.com/\r\n"),
4519 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064520 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:294521 };
4522
4523 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4524 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:064525 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:294526
4527 session_deps.socket_factory.AddSocketDataProvider(&data);
4528 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4529
[email protected]49639fa2011-12-20 23:22:414530 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294531
4532 scoped_ptr<HttpTransaction> trans(
4533 new HttpNetworkTransaction(CreateSession(&session_deps)));
4534
[email protected]49639fa2011-12-20 23:22:414535 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294536 EXPECT_EQ(ERR_IO_PENDING, rv);
4537
4538 rv = callback.WaitForResult();
4539 EXPECT_EQ(OK, rv);
4540 const HttpResponseInfo* response = trans->GetResponseInfo();
4541
[email protected]fe2255a2011-09-20 19:37:504542 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294543
4544 EXPECT_EQ(302, response->headers->response_code());
4545 std::string url;
4546 EXPECT_TRUE(response->headers->IsRedirect(&url));
4547 EXPECT_EQ("http://login.example.com/", url);
4548}
4549
4550// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4551TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4552 SessionDependencies session_deps(
4553 ProxyService::CreateFixed("https://proxy:70"));
4554
4555 HttpRequestInfo request;
4556 request.method = "GET";
4557 request.url = GURL("https://www.google.com/");
4558 request.load_flags = 0;
4559
4560 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4561 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4562 MockWrite data_writes[] = {
[email protected]8ddf8322012-02-23 18:08:064563 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:294564 };
4565
4566 static const char* const kExtraHeaders[] = {
4567 "location",
4568 "http://login.example.com/",
4569 };
4570 scoped_ptr<spdy::SpdyFrame> resp(
4571 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4572 arraysize(kExtraHeaders)/2, 1));
4573 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:064574 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
4575 MockRead(ASYNC, 0, 2), // EOF
[email protected]511f6f52010-12-17 03:58:294576 };
4577
[email protected]a1595312012-01-22 03:25:044578 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294579 new DelayedSocketData(
4580 1, // wait for one write to finish before reading.
4581 data_reads, arraysize(data_reads),
4582 data_writes, arraysize(data_writes)));
[email protected]8ddf8322012-02-23 18:08:064583 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]e58c1b82012-02-22 23:07:514584 proxy_ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]511f6f52010-12-17 03:58:294585
4586 session_deps.socket_factory.AddSocketDataProvider(data.get());
4587 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4588
[email protected]49639fa2011-12-20 23:22:414589 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294590
4591 scoped_ptr<HttpTransaction> trans(
4592 new HttpNetworkTransaction(CreateSession(&session_deps)));
4593
[email protected]49639fa2011-12-20 23:22:414594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294595 EXPECT_EQ(ERR_IO_PENDING, rv);
4596
4597 rv = callback.WaitForResult();
4598 EXPECT_EQ(OK, rv);
4599 const HttpResponseInfo* response = trans->GetResponseInfo();
4600
[email protected]fe2255a2011-09-20 19:37:504601 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294602
4603 EXPECT_EQ(302, response->headers->response_code());
4604 std::string url;
4605 EXPECT_TRUE(response->headers->IsRedirect(&url));
4606 EXPECT_EQ("http://login.example.com/", url);
4607}
4608
4609// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4610TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4611 SessionDependencies session_deps(
4612 ProxyService::CreateFixed("https://proxy:70"));
4613
4614 HttpRequestInfo request;
4615 request.method = "GET";
4616 request.url = GURL("https://www.google.com/");
4617 request.load_flags = 0;
4618
4619 MockWrite data_writes[] = {
4620 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4621 "Host: www.google.com\r\n"
4622 "Proxy-Connection: keep-alive\r\n\r\n"),
4623 };
4624
4625 MockRead data_reads[] = {
4626 MockRead("HTTP/1.1 404 Not Found\r\n"),
4627 MockRead("Content-Length: 23\r\n\r\n"),
4628 MockRead("The host does not exist"),
[email protected]8ddf8322012-02-23 18:08:064629 MockRead(SYNCHRONOUS, OK),
[email protected]511f6f52010-12-17 03:58:294630 };
4631
4632 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4633 data_writes, arraysize(data_writes));
[email protected]8ddf8322012-02-23 18:08:064634 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]511f6f52010-12-17 03:58:294635
4636 session_deps.socket_factory.AddSocketDataProvider(&data);
4637 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4638
[email protected]49639fa2011-12-20 23:22:414639 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294640
4641 scoped_ptr<HttpTransaction> trans(
4642 new HttpNetworkTransaction(CreateSession(&session_deps)));
4643
[email protected]49639fa2011-12-20 23:22:414644 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294645 EXPECT_EQ(ERR_IO_PENDING, rv);
4646
4647 rv = callback.WaitForResult();
4648 EXPECT_EQ(OK, rv);
4649 const HttpResponseInfo* response = trans->GetResponseInfo();
4650
[email protected]fe2255a2011-09-20 19:37:504651 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294652
4653 EXPECT_EQ(404, response->headers->response_code());
4654 EXPECT_EQ(23, response->headers->GetContentLength());
4655 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4656 EXPECT_FALSE(response->ssl_info.is_valid());
4657
4658 std::string response_data;
4659 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4660 EXPECT_EQ("The host does not exist", response_data);
4661}
4662
4663// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4664// request
4665TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4666 SessionDependencies session_deps(
4667 ProxyService::CreateFixed("https://proxy:70"));
4668
4669 HttpRequestInfo request;
4670 request.method = "GET";
4671 request.url = GURL("https://www.google.com/");
4672 request.load_flags = 0;
4673
4674 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4675 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4676 MockWrite data_writes[] = {
[email protected]8ddf8322012-02-23 18:08:064677 CreateMockWrite(*conn.get(), 0, SYNCHRONOUS),
[email protected]511f6f52010-12-17 03:58:294678 };
4679
4680 static const char* const kExtraHeaders[] = {
4681 "location",
4682 "http://login.example.com/",
4683 };
4684 scoped_ptr<spdy::SpdyFrame> resp(
4685 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4686 arraysize(kExtraHeaders)/2, 1));
4687 scoped_ptr<spdy::SpdyFrame> body(
4688 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4689 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:064690 CreateMockRead(*resp.get(), 1, SYNCHRONOUS),
4691 CreateMockRead(*body.get(), 2, SYNCHRONOUS),
4692 MockRead(ASYNC, 0, 3), // EOF
[email protected]511f6f52010-12-17 03:58:294693 };
4694
[email protected]a1595312012-01-22 03:25:044695 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294696 new DelayedSocketData(
4697 1, // wait for one write to finish before reading.
4698 data_reads, arraysize(data_reads),
4699 data_writes, arraysize(data_writes)));
[email protected]8ddf8322012-02-23 18:08:064700 SSLSocketDataProvider proxy_ssl(ASYNC, OK); // SSL to the proxy
[email protected]e58c1b82012-02-22 23:07:514701 proxy_ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]511f6f52010-12-17 03:58:294702
4703 session_deps.socket_factory.AddSocketDataProvider(data.get());
4704 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4705
[email protected]49639fa2011-12-20 23:22:414706 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294707
4708 scoped_ptr<HttpTransaction> trans(
4709 new HttpNetworkTransaction(CreateSession(&session_deps)));
4710
[email protected]49639fa2011-12-20 23:22:414711 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294712 EXPECT_EQ(ERR_IO_PENDING, rv);
4713
4714 rv = callback.WaitForResult();
4715 EXPECT_EQ(OK, rv);
4716 const HttpResponseInfo* response = trans->GetResponseInfo();
4717
[email protected]fe2255a2011-09-20 19:37:504718 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294719
4720 EXPECT_EQ(404, response->headers->response_code());
4721 EXPECT_FALSE(response->ssl_info.is_valid());
4722
4723 std::string response_data;
4724 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4725 EXPECT_EQ("The host does not exist", response_data);
4726}
4727
[email protected]0c5fb722012-02-28 11:50:354728// Test the request-challenge-retry sequence for basic auth, through
4729// a SPDY proxy over a single SPDY session.
4730TEST_F(HttpNetworkTransactionTest, BasicAuthSpdyProxy) {
4731 HttpRequestInfo request;
4732 request.method = "GET";
4733 request.url = GURL("https://www.google.com/");
4734 // when the no authentication data flag is set.
4735 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
4736
4737 // Configure against https proxy server "myproxy:70".
4738 SessionDependencies session_deps(
4739 ProxyService::CreateFixed("https://myproxy:70"));
4740 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
4741 session_deps.net_log = log.bound().net_log();
4742 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
4743
4744 // Since we have proxy, should try to establish tunnel.
4745 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyConnect(NULL, 0, 1));
4746 scoped_ptr<spdy::SpdyFrame> rst(ConstructSpdyRstStream(1, spdy::CANCEL));
4747
4748 // After calling trans->RestartWithAuth(), this is the request we should
4749 // be issuing -- the final header line contains the credentials.
4750 const char* const kAuthCredentials[] = {
4751 "proxy-authorization", "Basic Zm9vOmJhcg==",
4752 };
4753 scoped_ptr<spdy::SpdyFrame> connect2(
4754 ConstructSpdyConnect(kAuthCredentials, arraysize(kAuthCredentials)/2, 3));
4755 // fetch https://www.google.com/ via HTTP
4756 const char get[] = "GET / HTTP/1.1\r\n"
4757 "Host: www.google.com\r\n"
4758 "Connection: keep-alive\r\n\r\n";
4759 scoped_ptr<spdy::SpdyFrame> wrapped_get(
4760 ConstructSpdyBodyFrame(3, get, strlen(get), false));
4761
4762 MockWrite spdy_writes[] = {
4763 CreateMockWrite(*req, 0, ASYNC),
4764 CreateMockWrite(*rst, 2, ASYNC),
4765 CreateMockWrite(*connect2, 3),
4766 CreateMockWrite(*wrapped_get, 5)
4767 };
4768
4769 // The proxy responds to the connect with a 407, using a persistent
4770 // connection.
4771 const char* const kAuthChallenge[] = {
4772 "status", "407 Proxy Authentication Required",
4773 "version", "HTTP/1.1",
4774 "proxy-authenticate", "Basic realm=\"MyRealm1\"",
4775 };
4776
4777 scoped_ptr<spdy::SpdyFrame> conn_auth_resp(
4778 ConstructSpdyControlFrame(NULL,
4779 0,
4780 false,
4781 1,
4782 LOWEST,
4783 spdy::SYN_REPLY,
4784 spdy::CONTROL_FLAG_NONE,
4785 kAuthChallenge,
4786 arraysize(kAuthChallenge)));
4787
4788 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
4789 const char resp[] = "HTTP/1.1 200 OK\r\n"
4790 "Content-Length: 5\r\n\r\n";
4791
4792 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
4793 ConstructSpdyBodyFrame(3, resp, strlen(resp), false));
4794 scoped_ptr<spdy::SpdyFrame> wrapped_body(
4795 ConstructSpdyBodyFrame(3, "hello", 5, false));
4796 MockRead spdy_reads[] = {
4797 CreateMockRead(*conn_auth_resp, 1, ASYNC),
4798 CreateMockRead(*conn_resp, 4, ASYNC),
4799 CreateMockRead(*wrapped_get_resp, 5, ASYNC),
4800 CreateMockRead(*wrapped_body, 6, ASYNC),
4801 MockRead(SYNCHRONOUS, ERR_IO_PENDING),
4802 };
4803
4804 scoped_ptr<OrderedSocketData> spdy_data(
4805 new OrderedSocketData(
4806 spdy_reads, arraysize(spdy_reads),
4807 spdy_writes, arraysize(spdy_writes)));
4808 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
4809 // Negotiate SPDY to the proxy
4810 SSLSocketDataProvider proxy(ASYNC, OK);
4811 proxy.SetNextProto(SSLClientSocket::kProtoSPDY2);
4812 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy);
4813 // Vanilla SSL to the server
4814 SSLSocketDataProvider server(ASYNC, OK);
4815 session_deps.socket_factory.AddSSLSocketDataProvider(&server);
4816
4817 TestCompletionCallback callback1;
4818
4819 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4820
4821 int rv = trans->Start(&request, callback1.callback(), log.bound());
4822 EXPECT_EQ(ERR_IO_PENDING, rv);
4823
4824 rv = callback1.WaitForResult();
4825 EXPECT_EQ(OK, rv);
4826 net::CapturingNetLog::EntryList entries;
4827 log.GetEntries(&entries);
4828 size_t pos = ExpectLogContainsSomewhere(
4829 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4830 NetLog::PHASE_NONE);
4831 ExpectLogContainsSomewhere(
4832 entries, pos,
4833 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4834 NetLog::PHASE_NONE);
4835
4836 const HttpResponseInfo* response = trans->GetResponseInfo();
4837 ASSERT_TRUE(response != NULL);
4838 ASSERT_FALSE(response->headers == NULL);
4839 EXPECT_EQ(407, response->headers->response_code());
4840 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4841 EXPECT_TRUE(response->auth_challenge.get() != NULL);
4842 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
4843
4844 TestCompletionCallback callback2;
4845
4846 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar),
4847 callback2.callback());
4848 EXPECT_EQ(ERR_IO_PENDING, rv);
4849
4850 rv = callback2.WaitForResult();
4851 EXPECT_EQ(OK, rv);
4852
4853 response = trans->GetResponseInfo();
4854 ASSERT_TRUE(response != NULL);
4855
4856 EXPECT_TRUE(response->headers->IsKeepAlive());
4857 EXPECT_EQ(200, response->headers->response_code());
4858 EXPECT_EQ(5, response->headers->GetContentLength());
4859 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4860
4861 // The password prompt info should not be set.
4862 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4863
4864 trans.reset();
4865 session->CloseAllConnections();
4866}
4867
[email protected]2df19bb2010-08-25 20:13:464868// Test HTTPS connections to a site with a bad certificate, going through an
4869// HTTPS proxy
4870TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114871 SessionDependencies session_deps(ProxyService::CreateFixed(
4872 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464873
4874 HttpRequestInfo request;
4875 request.method = "GET";
4876 request.url = GURL("https://www.google.com/");
4877 request.load_flags = 0;
4878
4879 // Attempt to fetch the URL from a server with a bad cert
4880 MockWrite bad_cert_writes[] = {
4881 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4882 "Host: www.google.com\r\n"
4883 "Proxy-Connection: keep-alive\r\n\r\n"),
4884 };
4885
4886 MockRead bad_cert_reads[] = {
4887 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064888 MockRead(SYNCHRONOUS, OK)
[email protected]2df19bb2010-08-25 20:13:464889 };
4890
4891 // Attempt to fetch the URL with a good cert
4892 MockWrite good_data_writes[] = {
4893 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4894 "Host: www.google.com\r\n"
4895 "Proxy-Connection: keep-alive\r\n\r\n"),
4896 MockWrite("GET / HTTP/1.1\r\n"
4897 "Host: www.google.com\r\n"
4898 "Connection: keep-alive\r\n\r\n"),
4899 };
4900
4901 MockRead good_cert_reads[] = {
4902 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4903 MockRead("HTTP/1.0 200 OK\r\n"),
4904 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4905 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064906 MockRead(SYNCHRONOUS, OK),
[email protected]2df19bb2010-08-25 20:13:464907 };
4908
4909 StaticSocketDataProvider ssl_bad_certificate(
4910 bad_cert_reads, arraysize(bad_cert_reads),
4911 bad_cert_writes, arraysize(bad_cert_writes));
4912 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4913 good_data_writes, arraysize(good_data_writes));
[email protected]8ddf8322012-02-23 18:08:064914 SSLSocketDataProvider ssl_bad(ASYNC, ERR_CERT_AUTHORITY_INVALID);
4915 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]2df19bb2010-08-25 20:13:464916
4917 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4918 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4919 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4920 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4921
4922 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4923 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4924 session_deps.socket_factory.AddSocketDataProvider(&data);
4925 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4926
[email protected]49639fa2011-12-20 23:22:414927 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464928
4929 scoped_ptr<HttpTransaction> trans(
4930 new HttpNetworkTransaction(CreateSession(&session_deps)));
4931
[email protected]49639fa2011-12-20 23:22:414932 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464933 EXPECT_EQ(ERR_IO_PENDING, rv);
4934
4935 rv = callback.WaitForResult();
4936 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4937
[email protected]49639fa2011-12-20 23:22:414938 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:464939 EXPECT_EQ(ERR_IO_PENDING, rv);
4940
4941 rv = callback.WaitForResult();
4942 EXPECT_EQ(OK, rv);
4943
4944 const HttpResponseInfo* response = trans->GetResponseInfo();
4945
[email protected]fe2255a2011-09-20 19:37:504946 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464947 EXPECT_EQ(100, response->headers->GetContentLength());
4948}
4949
[email protected]1c773ea12009-04-28 19:58:424950TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424951 HttpRequestInfo request;
4952 request.method = "GET";
4953 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434954 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4955 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424956
[email protected]cb9bf6ca2011-01-28 13:15:274957 SessionDependencies session_deps;
4958 scoped_ptr<HttpTransaction> trans(
4959 new HttpNetworkTransaction(CreateSession(&session_deps)));
4960
[email protected]1c773ea12009-04-28 19:58:424961 MockWrite data_writes[] = {
4962 MockWrite("GET / HTTP/1.1\r\n"
4963 "Host: www.google.com\r\n"
4964 "Connection: keep-alive\r\n"
4965 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4966 };
4967
4968 // Lastly, the server responds with the actual content.
4969 MockRead data_reads[] = {
4970 MockRead("HTTP/1.0 200 OK\r\n"),
4971 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4972 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:064973 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:424974 };
4975
[email protected]31a2bfe2010-02-09 08:03:394976 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4977 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594978 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424979
[email protected]49639fa2011-12-20 23:22:414980 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424981
[email protected]49639fa2011-12-20 23:22:414982 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424983 EXPECT_EQ(ERR_IO_PENDING, rv);
4984
4985 rv = callback.WaitForResult();
4986 EXPECT_EQ(OK, rv);
4987}
4988
[email protected]da81f132010-08-18 23:39:294989TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294990 HttpRequestInfo request;
4991 request.method = "GET";
4992 request.url = GURL("https://www.google.com/");
4993 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4994 "Chromium Ultra Awesome X Edition");
4995
[email protected]cb9bf6ca2011-01-28 13:15:274996 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4997 scoped_ptr<HttpTransaction> trans(
4998 new HttpNetworkTransaction(CreateSession(&session_deps)));
4999
[email protected]da81f132010-08-18 23:39:295000 MockWrite data_writes[] = {
5001 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5002 "Host: www.google.com\r\n"
5003 "Proxy-Connection: keep-alive\r\n"
5004 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
5005 };
5006 MockRead data_reads[] = {
5007 // Return an error, so the transaction stops here (this test isn't
5008 // interested in the rest).
5009 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5010 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5011 MockRead("Proxy-Connection: close\r\n\r\n"),
5012 };
5013
5014 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5015 data_writes, arraysize(data_writes));
5016 session_deps.socket_factory.AddSocketDataProvider(&data);
5017
[email protected]49639fa2011-12-20 23:22:415018 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:295019
[email protected]49639fa2011-12-20 23:22:415020 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:295021 EXPECT_EQ(ERR_IO_PENDING, rv);
5022
5023 rv = callback.WaitForResult();
5024 EXPECT_EQ(OK, rv);
5025}
5026
[email protected]1c773ea12009-04-28 19:58:425027TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:425028 HttpRequestInfo request;
5029 request.method = "GET";
5030 request.url = GURL("http://www.google.com/");
5031 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:165032 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5033 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:425034
[email protected]cb9bf6ca2011-01-28 13:15:275035 SessionDependencies session_deps;
5036 scoped_ptr<HttpTransaction> trans(
5037 new HttpNetworkTransaction(CreateSession(&session_deps)));
5038
[email protected]1c773ea12009-04-28 19:58:425039 MockWrite data_writes[] = {
5040 MockWrite("GET / HTTP/1.1\r\n"
5041 "Host: www.google.com\r\n"
5042 "Connection: keep-alive\r\n"
5043 "Referer: http://the.previous.site.com/\r\n\r\n"),
5044 };
5045
5046 // Lastly, the server responds with the actual content.
5047 MockRead data_reads[] = {
5048 MockRead("HTTP/1.0 200 OK\r\n"),
5049 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5050 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065051 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:425052 };
5053
[email protected]31a2bfe2010-02-09 08:03:395054 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5055 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595056 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425057
[email protected]49639fa2011-12-20 23:22:415058 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425059
[email protected]49639fa2011-12-20 23:22:415060 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425061 EXPECT_EQ(ERR_IO_PENDING, rv);
5062
5063 rv = callback.WaitForResult();
5064 EXPECT_EQ(OK, rv);
5065}
5066
5067TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425068 HttpRequestInfo request;
5069 request.method = "POST";
5070 request.url = GURL("http://www.google.com/");
5071
[email protected]cb9bf6ca2011-01-28 13:15:275072 SessionDependencies session_deps;
5073 scoped_ptr<HttpTransaction> trans(
5074 new HttpNetworkTransaction(CreateSession(&session_deps)));
5075
[email protected]1c773ea12009-04-28 19:58:425076 MockWrite data_writes[] = {
5077 MockWrite("POST / HTTP/1.1\r\n"
5078 "Host: www.google.com\r\n"
5079 "Connection: keep-alive\r\n"
5080 "Content-Length: 0\r\n\r\n"),
5081 };
5082
5083 // Lastly, the server responds with the actual content.
5084 MockRead data_reads[] = {
5085 MockRead("HTTP/1.0 200 OK\r\n"),
5086 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5087 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065088 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:425089 };
5090
[email protected]31a2bfe2010-02-09 08:03:395091 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5092 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595093 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425094
[email protected]49639fa2011-12-20 23:22:415095 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425096
[email protected]49639fa2011-12-20 23:22:415097 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425098 EXPECT_EQ(ERR_IO_PENDING, rv);
5099
5100 rv = callback.WaitForResult();
5101 EXPECT_EQ(OK, rv);
5102}
5103
5104TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425105 HttpRequestInfo request;
5106 request.method = "PUT";
5107 request.url = GURL("http://www.google.com/");
5108
[email protected]cb9bf6ca2011-01-28 13:15:275109 SessionDependencies session_deps;
5110 scoped_ptr<HttpTransaction> trans(
5111 new HttpNetworkTransaction(CreateSession(&session_deps)));
5112
[email protected]1c773ea12009-04-28 19:58:425113 MockWrite data_writes[] = {
5114 MockWrite("PUT / HTTP/1.1\r\n"
5115 "Host: www.google.com\r\n"
5116 "Connection: keep-alive\r\n"
5117 "Content-Length: 0\r\n\r\n"),
5118 };
5119
5120 // Lastly, the server responds with the actual content.
5121 MockRead data_reads[] = {
5122 MockRead("HTTP/1.0 200 OK\r\n"),
5123 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5124 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065125 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:425126 };
5127
[email protected]31a2bfe2010-02-09 08:03:395128 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5129 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595130 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425131
[email protected]49639fa2011-12-20 23:22:415132 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425133
[email protected]49639fa2011-12-20 23:22:415134 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425135 EXPECT_EQ(ERR_IO_PENDING, rv);
5136
5137 rv = callback.WaitForResult();
5138 EXPECT_EQ(OK, rv);
5139}
5140
5141TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425142 HttpRequestInfo request;
5143 request.method = "HEAD";
5144 request.url = GURL("http://www.google.com/");
5145
[email protected]cb9bf6ca2011-01-28 13:15:275146 SessionDependencies session_deps;
5147 scoped_ptr<HttpTransaction> trans(
5148 new HttpNetworkTransaction(CreateSession(&session_deps)));
5149
[email protected]1c773ea12009-04-28 19:58:425150 MockWrite data_writes[] = {
5151 MockWrite("HEAD / HTTP/1.1\r\n"
5152 "Host: www.google.com\r\n"
5153 "Connection: keep-alive\r\n"
5154 "Content-Length: 0\r\n\r\n"),
5155 };
5156
5157 // Lastly, the server responds with the actual content.
5158 MockRead data_reads[] = {
5159 MockRead("HTTP/1.0 200 OK\r\n"),
5160 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5161 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065162 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:425163 };
5164
[email protected]31a2bfe2010-02-09 08:03:395165 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5166 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595167 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425168
[email protected]49639fa2011-12-20 23:22:415169 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425170
[email protected]49639fa2011-12-20 23:22:415171 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425172 EXPECT_EQ(ERR_IO_PENDING, rv);
5173
5174 rv = callback.WaitForResult();
5175 EXPECT_EQ(OK, rv);
5176}
5177
5178TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425179 HttpRequestInfo request;
5180 request.method = "GET";
5181 request.url = GURL("http://www.google.com/");
5182 request.load_flags = LOAD_BYPASS_CACHE;
5183
[email protected]cb9bf6ca2011-01-28 13:15:275184 SessionDependencies session_deps;
5185 scoped_ptr<HttpTransaction> trans(
5186 new HttpNetworkTransaction(CreateSession(&session_deps)));
5187
[email protected]1c773ea12009-04-28 19:58:425188 MockWrite data_writes[] = {
5189 MockWrite("GET / HTTP/1.1\r\n"
5190 "Host: www.google.com\r\n"
5191 "Connection: keep-alive\r\n"
5192 "Pragma: no-cache\r\n"
5193 "Cache-Control: no-cache\r\n\r\n"),
5194 };
5195
5196 // Lastly, the server responds with the actual content.
5197 MockRead data_reads[] = {
5198 MockRead("HTTP/1.0 200 OK\r\n"),
5199 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5200 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065201 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:425202 };
5203
[email protected]31a2bfe2010-02-09 08:03:395204 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5205 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595206 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425207
[email protected]49639fa2011-12-20 23:22:415208 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425209
[email protected]49639fa2011-12-20 23:22:415210 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425211 EXPECT_EQ(ERR_IO_PENDING, rv);
5212
5213 rv = callback.WaitForResult();
5214 EXPECT_EQ(OK, rv);
5215}
5216
5217TEST_F(HttpNetworkTransactionTest,
5218 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425219 HttpRequestInfo request;
5220 request.method = "GET";
5221 request.url = GURL("http://www.google.com/");
5222 request.load_flags = LOAD_VALIDATE_CACHE;
5223
[email protected]cb9bf6ca2011-01-28 13:15:275224 SessionDependencies session_deps;
5225 scoped_ptr<HttpTransaction> trans(
5226 new HttpNetworkTransaction(CreateSession(&session_deps)));
5227
[email protected]1c773ea12009-04-28 19:58:425228 MockWrite data_writes[] = {
5229 MockWrite("GET / HTTP/1.1\r\n"
5230 "Host: www.google.com\r\n"
5231 "Connection: keep-alive\r\n"
5232 "Cache-Control: max-age=0\r\n\r\n"),
5233 };
5234
5235 // Lastly, the server responds with the actual content.
5236 MockRead data_reads[] = {
5237 MockRead("HTTP/1.0 200 OK\r\n"),
5238 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5239 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065240 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:425241 };
5242
[email protected]31a2bfe2010-02-09 08:03:395243 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5244 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595245 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425246
[email protected]49639fa2011-12-20 23:22:415247 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425248
[email protected]49639fa2011-12-20 23:22:415249 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425250 EXPECT_EQ(ERR_IO_PENDING, rv);
5251
5252 rv = callback.WaitForResult();
5253 EXPECT_EQ(OK, rv);
5254}
5255
5256TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425257 HttpRequestInfo request;
5258 request.method = "GET";
5259 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435260 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425261
[email protected]cb9bf6ca2011-01-28 13:15:275262 SessionDependencies session_deps;
5263 scoped_ptr<HttpTransaction> trans(
5264 new HttpNetworkTransaction(CreateSession(&session_deps)));
5265
[email protected]1c773ea12009-04-28 19:58:425266 MockWrite data_writes[] = {
5267 MockWrite("GET / HTTP/1.1\r\n"
5268 "Host: www.google.com\r\n"
5269 "Connection: keep-alive\r\n"
5270 "FooHeader: Bar\r\n\r\n"),
5271 };
5272
5273 // Lastly, the server responds with the actual content.
5274 MockRead data_reads[] = {
5275 MockRead("HTTP/1.0 200 OK\r\n"),
5276 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5277 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065278 MockRead(SYNCHRONOUS, OK),
[email protected]1c773ea12009-04-28 19:58:425279 };
5280
[email protected]31a2bfe2010-02-09 08:03:395281 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5282 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595283 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425284
[email protected]49639fa2011-12-20 23:22:415285 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425286
[email protected]49639fa2011-12-20 23:22:415287 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425288 EXPECT_EQ(ERR_IO_PENDING, rv);
5289
5290 rv = callback.WaitForResult();
5291 EXPECT_EQ(OK, rv);
5292}
5293
[email protected]270c6412010-03-29 22:02:475294TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475295 HttpRequestInfo request;
5296 request.method = "GET";
5297 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435298 request.extra_headers.SetHeader("referer", "www.foo.com");
5299 request.extra_headers.SetHeader("hEllo", "Kitty");
5300 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475301
[email protected]cb9bf6ca2011-01-28 13:15:275302 SessionDependencies session_deps;
5303 scoped_ptr<HttpTransaction> trans(
5304 new HttpNetworkTransaction(CreateSession(&session_deps)));
5305
[email protected]270c6412010-03-29 22:02:475306 MockWrite data_writes[] = {
5307 MockWrite("GET / HTTP/1.1\r\n"
5308 "Host: www.google.com\r\n"
5309 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165310 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475311 "hEllo: Kitty\r\n"
5312 "FoO: bar\r\n\r\n"),
5313 };
5314
5315 // Lastly, the server responds with the actual content.
5316 MockRead data_reads[] = {
5317 MockRead("HTTP/1.0 200 OK\r\n"),
5318 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5319 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:065320 MockRead(SYNCHRONOUS, OK),
[email protected]270c6412010-03-29 22:02:475321 };
5322
5323 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5324 data_writes, arraysize(data_writes));
5325 session_deps.socket_factory.AddSocketDataProvider(&data);
5326
[email protected]49639fa2011-12-20 23:22:415327 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:475328
[email protected]49639fa2011-12-20 23:22:415329 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:475330 EXPECT_EQ(ERR_IO_PENDING, rv);
5331
5332 rv = callback.WaitForResult();
5333 EXPECT_EQ(OK, rv);
5334}
5335
[email protected]9ef1d98e2012-02-14 00:34:125336// http://crbug.com/112682
[email protected]ee0b1012012-02-04 04:30:255337#if defined(OS_MACOSX)
[email protected]9ef1d98e2012-02-14 00:34:125338#define MAYBE_SOCKS4_HTTP_GET DISABLED_SOCKS4_HTTP_GET
[email protected]ee0b1012012-02-04 04:30:255339#else
5340#define MAYBE_SOCKS4_HTTP_GET SOCKS4_HTTP_GET
5341#endif
5342
5343TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_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("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025351
5352 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435353 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025354
[email protected]3cd17242009-06-23 02:59:025355 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5356 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5357
5358 MockWrite data_writes[] = {
[email protected]8ddf8322012-02-23 18:08:065359 MockWrite(ASYNC, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025360 MockWrite("GET / HTTP/1.1\r\n"
5361 "Host: www.google.com\r\n"
5362 "Connection: keep-alive\r\n\r\n")
5363 };
5364
5365 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:065366 MockRead(ASYNC, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025367 MockRead("HTTP/1.0 200 OK\r\n"),
5368 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5369 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:065370 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:025371 };
5372
[email protected]31a2bfe2010-02-09 08:03:395373 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5374 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595375 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025376
[email protected]49639fa2011-12-20 23:22:415377 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025378
[email protected]49639fa2011-12-20 23:22:415379 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025380 EXPECT_EQ(ERR_IO_PENDING, rv);
5381
5382 rv = callback.WaitForResult();
5383 EXPECT_EQ(OK, rv);
5384
5385 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505386 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025387
5388 std::string response_text;
5389 rv = ReadTransaction(trans.get(), &response_text);
5390 EXPECT_EQ(OK, rv);
5391 EXPECT_EQ("Payload", response_text);
5392}
5393
[email protected]9ef1d98e2012-02-14 00:34:125394// http://crbug.com/112682
[email protected]ee0b1012012-02-04 04:30:255395#if defined(OS_MACOSX)
[email protected]9ef1d98e2012-02-14 00:34:125396#define MAYBE_SOCKS4_SSL_GET DISABLED_SOCKS4_SSL_GET
[email protected]ee0b1012012-02-04 04:30:255397#else
5398#define MAYBE_SOCKS4_SSL_GET SOCKS4_SSL_GET
5399#endif
5400
5401TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275402 HttpRequestInfo request;
5403 request.method = "GET";
5404 request.url = GURL("https://www.google.com/");
5405 request.load_flags = 0;
5406
[email protected]80d6524d2009-08-18 03:58:095407 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005408 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025409
5410 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435411 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025412
[email protected]3cd17242009-06-23 02:59:025413 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5414 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5415
5416 MockWrite data_writes[] = {
[email protected]8ddf8322012-02-23 18:08:065417 MockWrite(ASYNC, reinterpret_cast<char*>(write_buffer),
[email protected]e0c27be2009-07-15 13:09:355418 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025419 MockWrite("GET / HTTP/1.1\r\n"
5420 "Host: www.google.com\r\n"
5421 "Connection: keep-alive\r\n\r\n")
5422 };
5423
5424 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:065425 MockWrite(ASYNC, reinterpret_cast<char*>(read_buffer),
[email protected]e0c27be2009-07-15 13:09:355426 arraysize(read_buffer)),
5427 MockRead("HTTP/1.0 200 OK\r\n"),
5428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5429 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:065430 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:355431 };
5432
[email protected]31a2bfe2010-02-09 08:03:395433 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5434 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595435 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355436
[email protected]8ddf8322012-02-23 18:08:065437 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]5ecc992a42009-11-11 01:41:595438 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355439
[email protected]49639fa2011-12-20 23:22:415440 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355441
[email protected]49639fa2011-12-20 23:22:415442 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355443 EXPECT_EQ(ERR_IO_PENDING, rv);
5444
5445 rv = callback.WaitForResult();
5446 EXPECT_EQ(OK, rv);
5447
5448 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505449 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355450
5451 std::string response_text;
5452 rv = ReadTransaction(trans.get(), &response_text);
5453 EXPECT_EQ(OK, rv);
5454 EXPECT_EQ("Payload", response_text);
5455}
5456
5457TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275458 HttpRequestInfo request;
5459 request.method = "GET";
5460 request.url = GURL("http://www.google.com/");
5461 request.load_flags = 0;
5462
[email protected]80d6524d2009-08-18 03:58:095463 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005464 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355465
5466 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435467 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355468
[email protected]e0c27be2009-07-15 13:09:355469 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5470 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375471 const char kSOCKS5OkRequest[] = {
5472 0x05, // Version
5473 0x01, // Command (CONNECT)
5474 0x00, // Reserved.
5475 0x03, // Address type (DOMAINNAME).
5476 0x0E, // Length of domain (14)
5477 // Domain string:
5478 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5479 0x00, 0x50, // 16-bit port (80)
5480 };
[email protected]e0c27be2009-07-15 13:09:355481 const char kSOCKS5OkResponse[] =
5482 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5483
5484 MockWrite data_writes[] = {
[email protected]8ddf8322012-02-23 18:08:065485 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5486 MockWrite(ASYNC, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
[email protected]e0c27be2009-07-15 13:09:355487 MockWrite("GET / HTTP/1.1\r\n"
5488 "Host: www.google.com\r\n"
5489 "Connection: keep-alive\r\n\r\n")
5490 };
5491
5492 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:065493 MockWrite(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5494 MockWrite(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]e0c27be2009-07-15 13:09:355495 MockRead("HTTP/1.0 200 OK\r\n"),
5496 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5497 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:065498 MockRead(SYNCHRONOUS, OK)
[email protected]e0c27be2009-07-15 13:09:355499 };
5500
[email protected]31a2bfe2010-02-09 08:03:395501 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5502 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595503 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355504
[email protected]49639fa2011-12-20 23:22:415505 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355506
[email protected]49639fa2011-12-20 23:22:415507 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355508 EXPECT_EQ(ERR_IO_PENDING, rv);
5509
5510 rv = callback.WaitForResult();
5511 EXPECT_EQ(OK, rv);
5512
5513 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505514 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355515
5516 std::string response_text;
5517 rv = ReadTransaction(trans.get(), &response_text);
5518 EXPECT_EQ(OK, rv);
5519 EXPECT_EQ("Payload", response_text);
5520}
5521
5522TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275523 HttpRequestInfo request;
5524 request.method = "GET";
5525 request.url = GURL("https://www.google.com/");
5526 request.load_flags = 0;
5527
[email protected]80d6524d2009-08-18 03:58:095528 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005529 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355530
5531 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435532 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355533
[email protected]e0c27be2009-07-15 13:09:355534 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5535 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375536 const unsigned char kSOCKS5OkRequest[] = {
5537 0x05, // Version
5538 0x01, // Command (CONNECT)
5539 0x00, // Reserved.
5540 0x03, // Address type (DOMAINNAME).
5541 0x0E, // Length of domain (14)
5542 // Domain string:
5543 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5544 0x01, 0xBB, // 16-bit port (443)
5545 };
5546
[email protected]e0c27be2009-07-15 13:09:355547 const char kSOCKS5OkResponse[] =
5548 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5549
5550 MockWrite data_writes[] = {
[email protected]8ddf8322012-02-23 18:08:065551 MockWrite(ASYNC, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5552 MockWrite(ASYNC, reinterpret_cast<const char*>(kSOCKS5OkRequest),
[email protected]e0c27be2009-07-15 13:09:355553 arraysize(kSOCKS5OkRequest)),
5554 MockWrite("GET / HTTP/1.1\r\n"
5555 "Host: www.google.com\r\n"
5556 "Connection: keep-alive\r\n\r\n")
5557 };
5558
5559 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:065560 MockWrite(ASYNC, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5561 MockWrite(ASYNC, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025562 MockRead("HTTP/1.0 200 OK\r\n"),
5563 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5564 MockRead("Payload"),
[email protected]8ddf8322012-02-23 18:08:065565 MockRead(SYNCHRONOUS, OK)
[email protected]3cd17242009-06-23 02:59:025566 };
5567
[email protected]31a2bfe2010-02-09 08:03:395568 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5569 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595570 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025571
[email protected]8ddf8322012-02-23 18:08:065572 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]5ecc992a42009-11-11 01:41:595573 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025574
[email protected]49639fa2011-12-20 23:22:415575 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025576
[email protected]49639fa2011-12-20 23:22:415577 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025578 EXPECT_EQ(ERR_IO_PENDING, rv);
5579
5580 rv = callback.WaitForResult();
5581 EXPECT_EQ(OK, rv);
5582
5583 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505584 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025585
5586 std::string response_text;
5587 rv = ReadTransaction(trans.get(), &response_text);
5588 EXPECT_EQ(OK, rv);
5589 EXPECT_EQ("Payload", response_text);
5590}
5591
[email protected]04e5be32009-06-26 20:00:315592// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065593
5594struct GroupNameTest {
5595 std::string proxy_server;
5596 std::string url;
5597 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185598 bool ssl;
[email protected]2d731a32010-04-29 01:04:065599};
5600
5601scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025602 SessionDependencies* session_deps) {
5603 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065604
[email protected]17291a022011-10-10 07:32:535605 HttpServerProperties* http_server_properties =
5606 session->http_server_properties();
5607 http_server_properties->SetAlternateProtocol(
[email protected]2d731a32010-04-29 01:04:065608 HostPortPair("host.with.alternate", 80), 443,
[email protected]8d2f7012012-02-16 00:08:045609 NPN_SPDY_21);
[email protected]2d731a32010-04-29 01:04:065610
5611 return session;
5612}
5613
5614int GroupNameTransactionHelper(
5615 const std::string& url,
5616 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065617 HttpRequestInfo request;
5618 request.method = "GET";
5619 request.url = GURL(url);
5620 request.load_flags = 0;
5621
[email protected]cb9bf6ca2011-01-28 13:15:275622 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5623
[email protected]49639fa2011-12-20 23:22:415624 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:065625
5626 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:415627 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:065628}
5629
5630TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5631 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315632 {
[email protected]2d731a32010-04-29 01:04:065633 "", // unused
[email protected]04e5be32009-06-26 20:00:315634 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545635 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185636 false,
[email protected]2ff8b312010-04-26 22:20:545637 },
5638 {
[email protected]2d731a32010-04-29 01:04:065639 "", // unused
[email protected]2ff8b312010-04-26 22:20:545640 "http://[2001:1418:13:1::25]/direct",
5641 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185642 false,
[email protected]04e5be32009-06-26 20:00:315643 },
[email protected]04e5be32009-06-26 20:00:315644
5645 // SSL Tests
5646 {
[email protected]2d731a32010-04-29 01:04:065647 "", // unused
[email protected]04e5be32009-06-26 20:00:315648 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025649 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185650 true,
[email protected]04e5be32009-06-26 20:00:315651 },
5652 {
[email protected]2d731a32010-04-29 01:04:065653 "", // unused
5654 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025655 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185656 true,
[email protected]04e5be32009-06-26 20:00:315657 },
5658 {
[email protected]2d731a32010-04-29 01:04:065659 "", // unused
[email protected]2ff8b312010-04-26 22:20:545660 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025661 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185662 true,
[email protected]2ff8b312010-04-26 22:20:545663 },
[email protected]2d731a32010-04-29 01:04:065664 };
[email protected]2ff8b312010-04-26 22:20:545665
[email protected]8e6441ca2010-08-19 05:56:385666 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065667
5668 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025669 SessionDependencies session_deps(
5670 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065671 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025672 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065673
5674 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285675 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5676 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135677 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345678 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025679 MockClientSocketPoolManager* mock_pool_manager =
5680 new MockClientSocketPoolManager;
5681 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
5682 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
5683 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065684
5685 EXPECT_EQ(ERR_IO_PENDING,
5686 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185687 if (tests[i].ssl)
5688 EXPECT_EQ(tests[i].expected_group_name,
5689 ssl_conn_pool->last_group_name_received());
5690 else
5691 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285692 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065693 }
5694
[email protected]8e6441ca2010-08-19 05:56:385695 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065696}
5697
5698TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5699 const GroupNameTest tests[] = {
5700 {
5701 "http_proxy",
5702 "http://www.google.com/http_proxy_normal",
5703 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185704 false,
[email protected]2d731a32010-04-29 01:04:065705 },
5706
5707 // SSL Tests
5708 {
5709 "http_proxy",
5710 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025711 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185712 true,
[email protected]2d731a32010-04-29 01:04:065713 },
[email protected]af3490e2010-10-16 21:02:295714
[email protected]9faeded92010-04-29 20:03:055715 {
5716 "http_proxy",
5717 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025718 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185719 true,
[email protected]9faeded92010-04-29 20:03:055720 },
[email protected]2d731a32010-04-29 01:04:065721 };
5722
[email protected]8e6441ca2010-08-19 05:56:385723 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065724
5725 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025726 SessionDependencies session_deps(
5727 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065728 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025729 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065730
5731 HttpNetworkSessionPeer peer(session);
5732
[email protected]e60e47a2010-07-14 03:37:185733 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135734 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345735 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135736 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345737 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025738
5739 MockClientSocketPoolManager* mock_pool_manager =
5740 new MockClientSocketPoolManager;
5741 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
5742 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5743 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065744
5745 EXPECT_EQ(ERR_IO_PENDING,
5746 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185747 if (tests[i].ssl)
5748 EXPECT_EQ(tests[i].expected_group_name,
5749 ssl_conn_pool->last_group_name_received());
5750 else
5751 EXPECT_EQ(tests[i].expected_group_name,
5752 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065753 }
5754
[email protected]8e6441ca2010-08-19 05:56:385755 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065756}
5757
5758TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5759 const GroupNameTest tests[] = {
5760 {
5761 "socks4://socks_proxy:1080",
5762 "http://www.google.com/socks4_direct",
5763 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185764 false,
[email protected]2d731a32010-04-29 01:04:065765 },
5766 {
5767 "socks5://socks_proxy:1080",
5768 "http://www.google.com/socks5_direct",
5769 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185770 false,
[email protected]2d731a32010-04-29 01:04:065771 },
5772
5773 // SSL Tests
5774 {
5775 "socks4://socks_proxy:1080",
5776 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025777 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185778 true,
[email protected]2d731a32010-04-29 01:04:065779 },
5780 {
5781 "socks5://socks_proxy:1080",
5782 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025783 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185784 true,
[email protected]2d731a32010-04-29 01:04:065785 },
[email protected]af3490e2010-10-16 21:02:295786
[email protected]9faeded92010-04-29 20:03:055787 {
5788 "socks4://socks_proxy:1080",
5789 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025790 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185791 true,
[email protected]9faeded92010-04-29 20:03:055792 },
[email protected]04e5be32009-06-26 20:00:315793 };
5794
[email protected]8e6441ca2010-08-19 05:56:385795 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545796
[email protected]04e5be32009-06-26 20:00:315797 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025798 SessionDependencies session_deps(
5799 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065800 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025801 SetupSessionForGroupNameTests(&session_deps));
5802
[email protected]2d731a32010-04-29 01:04:065803 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315804
[email protected]e60e47a2010-07-14 03:37:185805 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135806 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345807 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135808 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345809 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025810
5811 MockClientSocketPoolManager* mock_pool_manager =
5812 new MockClientSocketPoolManager;
5813 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
5814 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5815 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]04e5be32009-06-26 20:00:315816
[email protected]5695b8c2009-09-30 21:36:435817 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315818
[email protected]2d731a32010-04-29 01:04:065819 EXPECT_EQ(ERR_IO_PENDING,
5820 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185821 if (tests[i].ssl)
5822 EXPECT_EQ(tests[i].expected_group_name,
5823 ssl_conn_pool->last_group_name_received());
5824 else
5825 EXPECT_EQ(tests[i].expected_group_name,
5826 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315827 }
[email protected]2ff8b312010-04-26 22:20:545828
[email protected]8e6441ca2010-08-19 05:56:385829 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315830}
5831
[email protected]9172a982009-06-06 00:30:255832TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275833 HttpRequestInfo request;
5834 request.method = "GET";
5835 request.url = GURL("http://www.google.com/");
5836
[email protected]5c6a17e2009-06-10 00:54:545837 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005838 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325839
[email protected]69719062010-01-05 20:09:215840 // This simulates failure resolving all hostnames; that means we will fail
5841 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325842 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5843
[email protected]9172a982009-06-06 00:30:255844 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435845 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255846
[email protected]49639fa2011-12-20 23:22:415847 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:255848
[email protected]49639fa2011-12-20 23:22:415849 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:255850 EXPECT_EQ(ERR_IO_PENDING, rv);
5851
[email protected]9172a982009-06-06 00:30:255852 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015853 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255854}
5855
[email protected]685af592010-05-11 19:31:245856// Base test to make sure that when the load flags for a request specify to
5857// bypass the cache, the DNS cache is not used.
5858void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275859 // Issue a request, asking to bypass the cache(s).
5860 HttpRequestInfo request;
5861 request.method = "GET";
5862 request.load_flags = load_flags;
5863 request.url = GURL("http://www.google.com/");
5864
[email protected]3b9cca42009-06-16 01:08:285865 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325866
[email protected]a2c2fb92009-07-18 07:31:045867 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545868 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325869
[email protected]3b9cca42009-06-16 01:08:285870 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435871 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285872
[email protected]6e78dfb2011-07-28 21:34:475873 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285874 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:295875 TestCompletionCallback callback;
[email protected]94a0d3d92009-06-27 01:50:145876 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105877 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295878 callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:475879 EXPECT_EQ(ERR_IO_PENDING, rv);
5880 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285881 EXPECT_EQ(OK, rv);
5882
5883 // Verify that it was added to host cache, by doing a subsequent async lookup
5884 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465885 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105886 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295887 callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325888 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285889
5890 // Inject a failure the next time that "www.google.com" is resolved. This way
5891 // we can tell if the next lookup hit the cache, or the "network".
5892 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325893 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285894
5895 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5896 // first read -- this won't be reached as the host resolution will fail first.
[email protected]8ddf8322012-02-23 18:08:065897 MockRead data_reads[] = { MockRead(SYNCHRONOUS, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395898 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595899 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285900
[email protected]3b9cca42009-06-16 01:08:285901 // Run the request.
[email protected]49639fa2011-12-20 23:22:415902 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285903 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:415904 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285905
5906 // If we bypassed the cache, we would have gotten a failure while resolving
5907 // "www.google.com".
5908 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5909}
5910
[email protected]685af592010-05-11 19:31:245911// There are multiple load flags that should trigger the host cache bypass.
5912// Test each in isolation:
5913TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5914 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5915}
5916
5917TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5918 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5919}
5920
5921TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5922 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5923}
5924
[email protected]0877e3d2009-10-17 22:29:575925// Make sure we can handle an error when writing the request.
5926TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5927 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275928 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575929
5930 HttpRequestInfo request;
5931 request.method = "GET";
5932 request.url = GURL("http://www.foo.com/");
5933 request.load_flags = 0;
5934
5935 MockWrite write_failure[] = {
[email protected]8ddf8322012-02-23 18:08:065936 MockWrite(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:575937 };
[email protected]31a2bfe2010-02-09 08:03:395938 StaticSocketDataProvider data(NULL, 0,
5939 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595940 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575941
[email protected]49639fa2011-12-20 23:22:415942 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575943
5944 scoped_ptr<HttpTransaction> trans(
5945 new HttpNetworkTransaction(CreateSession(&session_deps)));
5946
[email protected]49639fa2011-12-20 23:22:415947 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575948 EXPECT_EQ(ERR_IO_PENDING, rv);
5949
5950 rv = callback.WaitForResult();
5951 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5952}
5953
5954// Check that a connection closed after the start of the headers finishes ok.
5955TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5956 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275957 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575958
5959 HttpRequestInfo request;
5960 request.method = "GET";
5961 request.url = GURL("http://www.foo.com/");
5962 request.load_flags = 0;
5963
5964 MockRead data_reads[] = {
5965 MockRead("HTTP/1."),
[email protected]8ddf8322012-02-23 18:08:065966 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:575967 };
5968
[email protected]31a2bfe2010-02-09 08:03:395969 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595970 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575971
[email protected]49639fa2011-12-20 23:22:415972 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575973
5974 scoped_ptr<HttpTransaction> trans(
5975 new HttpNetworkTransaction(CreateSession(&session_deps)));
5976
[email protected]49639fa2011-12-20 23:22:415977 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575978 EXPECT_EQ(ERR_IO_PENDING, rv);
5979
5980 rv = callback.WaitForResult();
5981 EXPECT_EQ(OK, rv);
5982
5983 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505984 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:575985
5986 EXPECT_TRUE(response->headers != NULL);
5987 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5988
5989 std::string response_data;
5990 rv = ReadTransaction(trans.get(), &response_data);
5991 EXPECT_EQ(OK, rv);
5992 EXPECT_EQ("", response_data);
5993}
5994
5995// Make sure that a dropped connection while draining the body for auth
5996// restart does the right thing.
5997TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5998 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275999 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:576000
6001 HttpRequestInfo request;
6002 request.method = "GET";
6003 request.url = GURL("http://www.google.com/");
6004 request.load_flags = 0;
6005
6006 MockWrite data_writes1[] = {
6007 MockWrite("GET / HTTP/1.1\r\n"
6008 "Host: www.google.com\r\n"
6009 "Connection: keep-alive\r\n\r\n"),
6010 };
6011
6012 MockRead data_reads1[] = {
6013 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6014 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6015 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6016 MockRead("Content-Length: 14\r\n\r\n"),
6017 MockRead("Unauth"),
[email protected]8ddf8322012-02-23 18:08:066018 MockRead(ASYNC, ERR_CONNECTION_RESET),
[email protected]0877e3d2009-10-17 22:29:576019 };
6020
[email protected]31a2bfe2010-02-09 08:03:396021 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6022 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:596023 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:576024
6025 // After calling trans->RestartWithAuth(), this is the request we should
6026 // be issuing -- the final header line contains the credentials.
6027 MockWrite data_writes2[] = {
6028 MockWrite("GET / HTTP/1.1\r\n"
6029 "Host: www.google.com\r\n"
6030 "Connection: keep-alive\r\n"
6031 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6032 };
6033
6034 // Lastly, the server responds with the actual content.
6035 MockRead data_reads2[] = {
6036 MockRead("HTTP/1.1 200 OK\r\n"),
6037 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6038 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066039 MockRead(SYNCHRONOUS, OK),
[email protected]0877e3d2009-10-17 22:29:576040 };
6041
[email protected]31a2bfe2010-02-09 08:03:396042 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6043 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:596044 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:576045
[email protected]49639fa2011-12-20 23:22:416046 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:576047
[email protected]0b0bf032010-09-21 18:08:506048 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6049
[email protected]49639fa2011-12-20 23:22:416050 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576051 EXPECT_EQ(ERR_IO_PENDING, rv);
6052
6053 rv = callback1.WaitForResult();
6054 EXPECT_EQ(OK, rv);
6055
6056 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506057 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046058 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:576059
[email protected]49639fa2011-12-20 23:22:416060 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:576061
[email protected]49639fa2011-12-20 23:22:416062 rv = trans->RestartWithAuth(
6063 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:576064 EXPECT_EQ(ERR_IO_PENDING, rv);
6065
6066 rv = callback2.WaitForResult();
6067 EXPECT_EQ(OK, rv);
6068
6069 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506070 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:576071 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6072 EXPECT_EQ(100, response->headers->GetContentLength());
6073}
6074
6075// Test HTTPS connections going through a proxy that sends extra data.
6076TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006077 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576078
6079 HttpRequestInfo request;
6080 request.method = "GET";
6081 request.url = GURL("https://www.google.com/");
6082 request.load_flags = 0;
6083
6084 MockRead proxy_reads[] = {
6085 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
[email protected]8ddf8322012-02-23 18:08:066086 MockRead(SYNCHRONOUS, OK)
[email protected]0877e3d2009-10-17 22:29:576087 };
6088
[email protected]31a2bfe2010-02-09 08:03:396089 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]8ddf8322012-02-23 18:08:066090 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]0877e3d2009-10-17 22:29:576091
[email protected]5ecc992a42009-11-11 01:41:596092 session_deps.socket_factory.AddSocketDataProvider(&data);
6093 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576094
[email protected]49639fa2011-12-20 23:22:416095 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:576096
6097 session_deps.socket_factory.ResetNextMockIndexes();
6098
6099 scoped_ptr<HttpTransaction> trans(
6100 new HttpNetworkTransaction(CreateSession(&session_deps)));
6101
[email protected]49639fa2011-12-20 23:22:416102 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576103 EXPECT_EQ(ERR_IO_PENDING, rv);
6104
6105 rv = callback.WaitForResult();
6106 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6107}
6108
[email protected]e22e1362009-11-23 21:31:126109TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466110 HttpRequestInfo request;
6111 request.method = "GET";
6112 request.url = GURL("http://www.google.com/");
6113 request.load_flags = 0;
6114
[email protected]cb9bf6ca2011-01-28 13:15:276115 SessionDependencies session_deps;
6116 scoped_ptr<HttpTransaction> trans(
6117 new HttpNetworkTransaction(CreateSession(&session_deps)));
6118
[email protected]e22e1362009-11-23 21:31:126119 MockRead data_reads[] = {
6120 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066121 MockRead(SYNCHRONOUS, OK),
[email protected]e22e1362009-11-23 21:31:126122 };
[email protected]9492e4a2010-02-24 00:58:466123
6124 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6125 session_deps.socket_factory.AddSocketDataProvider(&data);
6126
[email protected]49639fa2011-12-20 23:22:416127 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:466128
[email protected]49639fa2011-12-20 23:22:416129 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466130 EXPECT_EQ(ERR_IO_PENDING, rv);
6131
6132 EXPECT_EQ(OK, callback.WaitForResult());
6133
6134 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506135 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:466136
6137 EXPECT_TRUE(response->headers != NULL);
6138 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6139
6140 std::string response_data;
6141 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f001bd6a2011-12-08 04:31:376142 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126143}
6144
[email protected]95d88ffe2010-02-04 21:25:336145TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336146 HttpRequestInfo request;
6147 request.method = "POST";
6148 request.url = GURL("http://www.google.com/upload");
6149 request.upload_data = new UploadData;
6150 request.load_flags = 0;
6151
[email protected]cb9bf6ca2011-01-28 13:15:276152 SessionDependencies session_deps;
6153 scoped_ptr<HttpTransaction> trans(
6154 new HttpNetworkTransaction(CreateSession(&session_deps)));
6155
[email protected]95d88ffe2010-02-04 21:25:336156 FilePath temp_file_path;
6157 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6158 const uint64 kFakeSize = 100000; // file is actually blank
6159
6160 std::vector<UploadData::Element> elements;
6161 UploadData::Element element;
6162 element.SetToFilePath(temp_file_path);
6163 element.SetContentLength(kFakeSize);
6164 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536165 request.upload_data->SetElements(elements);
[email protected]1dce7082012-02-10 07:39:116166 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLengthSync());
[email protected]95d88ffe2010-02-04 21:25:336167
6168 MockRead data_reads[] = {
6169 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6170 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066171 MockRead(SYNCHRONOUS, OK),
[email protected]95d88ffe2010-02-04 21:25:336172 };
[email protected]31a2bfe2010-02-09 08:03:396173 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336174 session_deps.socket_factory.AddSocketDataProvider(&data);
6175
[email protected]49639fa2011-12-20 23:22:416176 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:336177
[email protected]49639fa2011-12-20 23:22:416178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336179 EXPECT_EQ(ERR_IO_PENDING, rv);
6180
6181 rv = callback.WaitForResult();
6182 EXPECT_EQ(OK, rv);
6183
6184 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506185 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:336186
6187 EXPECT_TRUE(response->headers != NULL);
6188 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6189
6190 std::string response_data;
6191 rv = ReadTransaction(trans.get(), &response_data);
6192 EXPECT_EQ(OK, rv);
6193 EXPECT_EQ("hello world", response_data);
6194
6195 file_util::Delete(temp_file_path, false);
6196}
6197
[email protected]6624b4622010-03-29 19:58:366198TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276199 HttpRequestInfo request;
6200 request.method = "POST";
6201 request.url = GURL("http://www.google.com/upload");
6202 request.upload_data = new UploadData;
6203 request.load_flags = 0;
6204
[email protected]6624b4622010-03-29 19:58:366205 // If we try to upload an unreadable file, the network stack should report
6206 // the file size as zero and upload zero bytes for that file.
6207 SessionDependencies session_deps;
6208 scoped_ptr<HttpTransaction> trans(
6209 new HttpNetworkTransaction(CreateSession(&session_deps)));
6210
6211 FilePath temp_file;
6212 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6213 std::string temp_file_content("Unreadable file.");
6214 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6215 temp_file_content.length()));
6216 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6217
[email protected]6624b4622010-03-29 19:58:366218 std::vector<UploadData::Element> elements;
6219 UploadData::Element element;
6220 element.SetToFilePath(temp_file);
6221 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536222 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366223
6224 MockRead data_reads[] = {
6225 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066226 MockRead(SYNCHRONOUS, OK),
[email protected]6624b4622010-03-29 19:58:366227 };
6228 MockWrite data_writes[] = {
6229 MockWrite("POST /upload HTTP/1.1\r\n"
6230 "Host: www.google.com\r\n"
6231 "Connection: keep-alive\r\n"
6232 "Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066233 MockWrite(SYNCHRONOUS, OK),
[email protected]6624b4622010-03-29 19:58:366234 };
6235 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6236 arraysize(data_writes));
6237 session_deps.socket_factory.AddSocketDataProvider(&data);
6238
[email protected]49639fa2011-12-20 23:22:416239 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:366240
[email protected]49639fa2011-12-20 23:22:416241 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366242 EXPECT_EQ(ERR_IO_PENDING, rv);
6243
6244 rv = callback.WaitForResult();
6245 EXPECT_EQ(OK, rv);
6246
6247 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506248 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366249 EXPECT_TRUE(response->headers != NULL);
6250 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6251
6252 file_util::Delete(temp_file, false);
6253}
6254
6255TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276256 HttpRequestInfo request;
6257 request.method = "POST";
6258 request.url = GURL("http://www.google.com/upload");
6259 request.upload_data = new UploadData;
6260 request.load_flags = 0;
6261
[email protected]6624b4622010-03-29 19:58:366262 SessionDependencies session_deps;
6263 scoped_ptr<HttpTransaction> trans(
6264 new HttpNetworkTransaction(CreateSession(&session_deps)));
6265
6266 FilePath temp_file;
6267 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6268 std::string temp_file_contents("Unreadable file.");
6269 std::string unreadable_contents(temp_file_contents.length(), '\0');
6270 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6271 temp_file_contents.length()));
6272
[email protected]6624b4622010-03-29 19:58:366273 std::vector<UploadData::Element> elements;
6274 UploadData::Element element;
6275 element.SetToFilePath(temp_file);
6276 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536277 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366278
6279 MockRead data_reads[] = {
6280 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6281 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6282 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6283
6284 MockRead("HTTP/1.1 200 OK\r\n"),
6285 MockRead("Content-Length: 0\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066286 MockRead(SYNCHRONOUS, OK),
[email protected]6624b4622010-03-29 19:58:366287 };
6288 MockWrite data_writes[] = {
6289 MockWrite("POST /upload HTTP/1.1\r\n"
6290 "Host: www.google.com\r\n"
6291 "Connection: keep-alive\r\n"
6292 "Content-Length: 16\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066293 MockWrite(SYNCHRONOUS, temp_file_contents.c_str()),
[email protected]6624b4622010-03-29 19:58:366294
6295 MockWrite("POST /upload HTTP/1.1\r\n"
6296 "Host: www.google.com\r\n"
6297 "Connection: keep-alive\r\n"
6298 "Content-Length: 16\r\n"
6299 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:066300 MockWrite(SYNCHRONOUS, unreadable_contents.c_str(),
6301 temp_file_contents.length()),
6302 MockWrite(SYNCHRONOUS, OK),
[email protected]6624b4622010-03-29 19:58:366303 };
6304 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6305 arraysize(data_writes));
6306 session_deps.socket_factory.AddSocketDataProvider(&data);
6307
[email protected]49639fa2011-12-20 23:22:416308 TestCompletionCallback callback1;
[email protected]6624b4622010-03-29 19:58:366309
[email protected]49639fa2011-12-20 23:22:416310 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366311 EXPECT_EQ(ERR_IO_PENDING, rv);
6312
6313 rv = callback1.WaitForResult();
6314 EXPECT_EQ(OK, rv);
6315
6316 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:046317 ASSERT_TRUE(response != NULL);
6318 ASSERT_TRUE(response->headers != NULL);
[email protected]6624b4622010-03-29 19:58:366319 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
[email protected]79cb5c12011-09-12 13:12:046320 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]6624b4622010-03-29 19:58:366321
6322 // Now make the file unreadable and try again.
6323 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6324
[email protected]49639fa2011-12-20 23:22:416325 TestCompletionCallback callback2;
[email protected]6624b4622010-03-29 19:58:366326
[email protected]49639fa2011-12-20 23:22:416327 rv = trans->RestartWithAuth(
6328 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]6624b4622010-03-29 19:58:366329 EXPECT_EQ(ERR_IO_PENDING, rv);
6330
6331 rv = callback2.WaitForResult();
6332 EXPECT_EQ(OK, rv);
6333
6334 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506335 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366336 EXPECT_TRUE(response->headers != NULL);
6337 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6338 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6339
6340 file_util::Delete(temp_file, false);
6341}
6342
[email protected]aeefc9e82010-02-19 16:18:276343// Tests that changes to Auth realms are treated like auth rejections.
6344TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6345 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276346
6347 HttpRequestInfo request;
6348 request.method = "GET";
6349 request.url = GURL("http://www.google.com/");
6350 request.load_flags = 0;
6351
6352 // First transaction will request a resource and receive a Basic challenge
6353 // with realm="first_realm".
6354 MockWrite data_writes1[] = {
6355 MockWrite("GET / HTTP/1.1\r\n"
6356 "Host: www.google.com\r\n"
6357 "Connection: keep-alive\r\n"
6358 "\r\n"),
6359 };
6360 MockRead data_reads1[] = {
6361 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6362 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6363 "\r\n"),
6364 };
6365
6366 // After calling trans->RestartWithAuth(), provide an Authentication header
6367 // for first_realm. The server will reject and provide a challenge with
6368 // second_realm.
6369 MockWrite data_writes2[] = {
6370 MockWrite("GET / HTTP/1.1\r\n"
6371 "Host: www.google.com\r\n"
6372 "Connection: keep-alive\r\n"
6373 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6374 "\r\n"),
6375 };
6376 MockRead data_reads2[] = {
6377 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6378 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6379 "\r\n"),
6380 };
6381
6382 // This again fails, and goes back to first_realm. Make sure that the
6383 // entry is removed from cache.
6384 MockWrite data_writes3[] = {
6385 MockWrite("GET / HTTP/1.1\r\n"
6386 "Host: www.google.com\r\n"
6387 "Connection: keep-alive\r\n"
6388 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6389 "\r\n"),
6390 };
6391 MockRead data_reads3[] = {
6392 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6393 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6394 "\r\n"),
6395 };
6396
6397 // Try one last time (with the correct password) and get the resource.
6398 MockWrite data_writes4[] = {
6399 MockWrite("GET / HTTP/1.1\r\n"
6400 "Host: www.google.com\r\n"
6401 "Connection: keep-alive\r\n"
6402 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6403 "\r\n"),
6404 };
6405 MockRead data_reads4[] = {
6406 MockRead("HTTP/1.1 200 OK\r\n"
6407 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506408 "Content-Length: 5\r\n"
6409 "\r\n"
6410 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276411 };
6412
6413 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6414 data_writes1, arraysize(data_writes1));
6415 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6416 data_writes2, arraysize(data_writes2));
6417 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6418 data_writes3, arraysize(data_writes3));
6419 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6420 data_writes4, arraysize(data_writes4));
6421 session_deps.socket_factory.AddSocketDataProvider(&data1);
6422 session_deps.socket_factory.AddSocketDataProvider(&data2);
6423 session_deps.socket_factory.AddSocketDataProvider(&data3);
6424 session_deps.socket_factory.AddSocketDataProvider(&data4);
6425
[email protected]49639fa2011-12-20 23:22:416426 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:276427
[email protected]0b0bf032010-09-21 18:08:506428 scoped_ptr<HttpTransaction> trans(
6429 new HttpNetworkTransaction(CreateSession(&session_deps)));
6430
[email protected]aeefc9e82010-02-19 16:18:276431 // Issue the first request with Authorize headers. There should be a
6432 // password prompt for first_realm waiting to be filled in after the
6433 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416434 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276435 EXPECT_EQ(ERR_IO_PENDING, rv);
6436 rv = callback1.WaitForResult();
6437 EXPECT_EQ(OK, rv);
6438 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506439 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046440 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6441 ASSERT_FALSE(challenge == NULL);
6442 EXPECT_FALSE(challenge->is_proxy);
6443 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6444 EXPECT_EQ("first_realm", challenge->realm);
6445 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276446
6447 // Issue the second request with an incorrect password. There should be a
6448 // password prompt for second_realm waiting to be filled in after the
6449 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416450 TestCompletionCallback callback2;
6451 rv = trans->RestartWithAuth(
6452 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:276453 EXPECT_EQ(ERR_IO_PENDING, rv);
6454 rv = callback2.WaitForResult();
6455 EXPECT_EQ(OK, rv);
6456 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506457 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046458 challenge = response->auth_challenge.get();
6459 ASSERT_FALSE(challenge == NULL);
6460 EXPECT_FALSE(challenge->is_proxy);
6461 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6462 EXPECT_EQ("second_realm", challenge->realm);
6463 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276464
6465 // Issue the third request with another incorrect password. There should be
6466 // a password prompt for first_realm waiting to be filled in. If the password
6467 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6468 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:416469 TestCompletionCallback callback3;
6470 rv = trans->RestartWithAuth(
6471 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:276472 EXPECT_EQ(ERR_IO_PENDING, rv);
6473 rv = callback3.WaitForResult();
6474 EXPECT_EQ(OK, rv);
6475 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506476 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046477 challenge = response->auth_challenge.get();
6478 ASSERT_FALSE(challenge == NULL);
6479 EXPECT_FALSE(challenge->is_proxy);
6480 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6481 EXPECT_EQ("first_realm", challenge->realm);
6482 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276483
6484 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:416485 TestCompletionCallback callback4;
6486 rv = trans->RestartWithAuth(
6487 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:276488 EXPECT_EQ(ERR_IO_PENDING, rv);
6489 rv = callback4.WaitForResult();
6490 EXPECT_EQ(OK, rv);
6491 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506492 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:276493 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6494}
6495
[email protected]564b4912010-03-09 16:30:426496TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386497 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:036498 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]a2cb8122010-03-10 17:22:426499
[email protected]564b4912010-03-09 16:30:426500 SessionDependencies session_deps;
6501
6502 MockRead data_reads[] = {
6503 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356504 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426505 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066506 MockRead(SYNCHRONOUS, OK),
[email protected]564b4912010-03-09 16:30:426507 };
6508
6509 HttpRequestInfo request;
6510 request.method = "GET";
6511 request.url = GURL("http://www.google.com/");
6512 request.load_flags = 0;
6513
6514 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6515
6516 session_deps.socket_factory.AddSocketDataProvider(&data);
6517
[email protected]49639fa2011-12-20 23:22:416518 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426519
6520 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6521 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6522
[email protected]49639fa2011-12-20 23:22:416523 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426524 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536525
[email protected]2fbaecf22010-07-22 22:20:356526 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]17291a022011-10-10 07:32:536527 const HttpServerProperties& http_server_properties =
6528 *session->http_server_properties();
[email protected]564b4912010-03-09 16:30:426529 EXPECT_FALSE(
[email protected]17291a022011-10-10 07:32:536530 http_server_properties.HasAlternateProtocol(http_host_port_pair));
[email protected]564b4912010-03-09 16:30:426531
6532 EXPECT_EQ(OK, callback.WaitForResult());
6533
6534 const HttpResponseInfo* response = trans->GetResponseInfo();
6535 ASSERT_TRUE(response != NULL);
6536 ASSERT_TRUE(response->headers != NULL);
6537 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536538 EXPECT_FALSE(response->was_fetched_via_spdy);
6539 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426540
6541 std::string response_data;
6542 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6543 EXPECT_EQ("hello world", response_data);
6544
[email protected]17291a022011-10-10 07:32:536545 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6546 const PortAlternateProtocolPair alternate =
6547 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6548 PortAlternateProtocolPair expected_alternate;
[email protected]564b4912010-03-09 16:30:426549 expected_alternate.port = 443;
[email protected]8d2f7012012-02-16 00:08:046550 expected_alternate.protocol = NPN_SPDY_21;
[email protected]564b4912010-03-09 16:30:426551 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426552
[email protected]8e6441ca2010-08-19 05:56:386553 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]ecf96e52012-03-03 00:43:036554 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]564b4912010-03-09 16:30:426555}
6556
[email protected]8b95ed62011-03-18 18:12:036557TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386558 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426559 SessionDependencies session_deps;
6560
6561 HttpRequestInfo request;
6562 request.method = "GET";
6563 request.url = GURL("http://www.google.com/");
6564 request.load_flags = 0;
6565
[email protected]d973e99a2012-02-17 21:02:366566 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]564b4912010-03-09 16:30:426567 StaticSocketDataProvider first_data;
6568 first_data.set_connect_data(mock_connect);
6569 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6570
6571 MockRead data_reads[] = {
6572 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6573 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066574 MockRead(ASYNC, OK),
[email protected]564b4912010-03-09 16:30:426575 };
6576 StaticSocketDataProvider second_data(
6577 data_reads, arraysize(data_reads), NULL, 0);
6578 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6579
[email protected]564b4912010-03-09 16:30:426580 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6581
[email protected]17291a022011-10-10 07:32:536582 HttpServerProperties* http_server_properties =
6583 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116584 // Port must be < 1024, or the header will be ignored (since initial port was
6585 // port 80 (another restricted port).
[email protected]17291a022011-10-10 07:32:536586 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116587 HostPortPair::FromURL(request.url),
6588 666 /* port is ignored by MockConnect anyway */,
[email protected]8d2f7012012-02-16 00:08:046589 NPN_SPDY_21);
[email protected]564b4912010-03-09 16:30:426590
6591 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416592 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426593
[email protected]49639fa2011-12-20 23:22:416594 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426595 EXPECT_EQ(ERR_IO_PENDING, rv);
6596 EXPECT_EQ(OK, callback.WaitForResult());
6597
6598 const HttpResponseInfo* response = trans->GetResponseInfo();
6599 ASSERT_TRUE(response != NULL);
6600 ASSERT_TRUE(response->headers != NULL);
6601 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6602
6603 std::string response_data;
6604 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6605 EXPECT_EQ("hello world", response_data);
6606
[email protected]17291a022011-10-10 07:32:536607 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116608 HostPortPair::FromURL(request.url)));
[email protected]17291a022011-10-10 07:32:536609 const PortAlternateProtocolPair alternate =
6610 http_server_properties->GetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116611 HostPortPair::FromURL(request.url));
[email protected]17291a022011-10-10 07:32:536612 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386613 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426614}
6615
[email protected]3912662a32011-10-04 00:51:116616TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6617 // Ensure that we're not allowed to redirect traffic via an alternate
6618 // protocol to an unrestricted (port >= 1024) when the original traffic was
6619 // on a restricted port (port < 1024). Ensure that we can redirect in all
6620 // other cases.
6621 HttpStreamFactory::set_use_alternate_protocols(true);
6622 SessionDependencies session_deps;
6623
6624 HttpRequestInfo restricted_port_request;
6625 restricted_port_request.method = "GET";
6626 restricted_port_request.url = GURL("http://www.google.com:1023/");
6627 restricted_port_request.load_flags = 0;
6628
[email protected]d973e99a2012-02-17 21:02:366629 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116630 StaticSocketDataProvider first_data;
6631 first_data.set_connect_data(mock_connect);
6632 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6633
6634 MockRead data_reads[] = {
6635 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6636 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066637 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:116638 };
6639 StaticSocketDataProvider second_data(
6640 data_reads, arraysize(data_reads), NULL, 0);
6641 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6642
6643 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6644
[email protected]17291a022011-10-10 07:32:536645 HttpServerProperties* http_server_properties =
6646 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116647 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536648 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116649 HostPortPair::FromURL(restricted_port_request.url),
6650 kUnrestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046651 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116652
6653 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416654 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116655
[email protected]49639fa2011-12-20 23:22:416656 int rv = trans->Start(
6657 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116658 EXPECT_EQ(ERR_IO_PENDING, rv);
6659 // Invalid change to unrestricted port should fail.
6660 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6661
6662 HttpStreamFactory::set_use_alternate_protocols(false);
6663}
6664
6665TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6666 // Ensure that we're not allowed to redirect traffic via an alternate
6667 // protocol to an unrestricted (port >= 1024) when the original traffic was
6668 // on a restricted port (port < 1024). Ensure that we can redirect in all
6669 // other cases.
6670 HttpStreamFactory::set_use_alternate_protocols(true);
6671 SessionDependencies session_deps;
6672
6673 HttpRequestInfo restricted_port_request;
6674 restricted_port_request.method = "GET";
6675 restricted_port_request.url = GURL("http://www.google.com:1023/");
6676 restricted_port_request.load_flags = 0;
6677
[email protected]d973e99a2012-02-17 21:02:366678 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116679 StaticSocketDataProvider first_data;
6680 first_data.set_connect_data(mock_connect);
6681 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6682
6683 MockRead data_reads[] = {
6684 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6685 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066686 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:116687 };
6688 StaticSocketDataProvider second_data(
6689 data_reads, arraysize(data_reads), NULL, 0);
6690 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6691
6692 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6693
[email protected]17291a022011-10-10 07:32:536694 HttpServerProperties* http_server_properties =
6695 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116696 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536697 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116698 HostPortPair::FromURL(restricted_port_request.url),
6699 kRestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046700 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116701
6702 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416703 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116704
[email protected]49639fa2011-12-20 23:22:416705 int rv = trans->Start(
6706 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116707 EXPECT_EQ(ERR_IO_PENDING, rv);
6708 // Valid change to restricted port should pass.
6709 EXPECT_EQ(OK, callback.WaitForResult());
6710
6711 HttpStreamFactory::set_use_alternate_protocols(false);
6712}
6713
6714TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6715 // Ensure that we're not allowed to redirect traffic via an alternate
6716 // protocol to an unrestricted (port >= 1024) when the original traffic was
6717 // on a restricted port (port < 1024). Ensure that we can redirect in all
6718 // other cases.
6719 HttpStreamFactory::set_use_alternate_protocols(true);
6720 SessionDependencies session_deps;
6721
6722 HttpRequestInfo unrestricted_port_request;
6723 unrestricted_port_request.method = "GET";
6724 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6725 unrestricted_port_request.load_flags = 0;
6726
[email protected]d973e99a2012-02-17 21:02:366727 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116728 StaticSocketDataProvider first_data;
6729 first_data.set_connect_data(mock_connect);
6730 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6731
6732 MockRead data_reads[] = {
6733 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6734 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066735 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:116736 };
6737 StaticSocketDataProvider second_data(
6738 data_reads, arraysize(data_reads), NULL, 0);
6739 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6740
6741 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6742
[email protected]17291a022011-10-10 07:32:536743 HttpServerProperties* http_server_properties =
6744 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116745 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536746 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116747 HostPortPair::FromURL(unrestricted_port_request.url),
6748 kRestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046749 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116750
6751 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416752 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116753
[email protected]49639fa2011-12-20 23:22:416754 int rv = trans->Start(
6755 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116756 EXPECT_EQ(ERR_IO_PENDING, rv);
6757 // Valid change to restricted port should pass.
6758 EXPECT_EQ(OK, callback.WaitForResult());
6759
6760 HttpStreamFactory::set_use_alternate_protocols(false);
6761}
6762
6763TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6764 // Ensure that we're not allowed to redirect traffic via an alternate
6765 // protocol to an unrestricted (port >= 1024) when the original traffic was
6766 // on a restricted port (port < 1024). Ensure that we can redirect in all
6767 // other cases.
6768 HttpStreamFactory::set_use_alternate_protocols(true);
6769 SessionDependencies session_deps;
6770
6771 HttpRequestInfo unrestricted_port_request;
6772 unrestricted_port_request.method = "GET";
6773 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6774 unrestricted_port_request.load_flags = 0;
6775
[email protected]d973e99a2012-02-17 21:02:366776 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED);
[email protected]3912662a32011-10-04 00:51:116777 StaticSocketDataProvider first_data;
6778 first_data.set_connect_data(mock_connect);
6779 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6780
6781 MockRead data_reads[] = {
6782 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6783 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066784 MockRead(ASYNC, OK),
[email protected]3912662a32011-10-04 00:51:116785 };
6786 StaticSocketDataProvider second_data(
6787 data_reads, arraysize(data_reads), NULL, 0);
6788 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6789
6790 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6791
[email protected]17291a022011-10-10 07:32:536792 HttpServerProperties* http_server_properties =
6793 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116794 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536795 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116796 HostPortPair::FromURL(unrestricted_port_request.url),
6797 kUnrestrictedAlternatePort,
[email protected]8d2f7012012-02-16 00:08:046798 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116799
6800 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416801 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116802
[email protected]49639fa2011-12-20 23:22:416803 int rv = trans->Start(
6804 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116805 EXPECT_EQ(ERR_IO_PENDING, rv);
6806 // Valid change to an unrestricted port should pass.
6807 EXPECT_EQ(OK, callback.WaitForResult());
6808
6809 HttpStreamFactory::set_use_alternate_protocols(false);
6810}
6811
[email protected]eb6234e2012-01-19 01:50:026812TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
6813 // Ensure that we're not allowed to redirect traffic via an alternate
6814 // protocol to an unsafe port, and that we resume the second
6815 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
6816 HttpStreamFactory::set_use_alternate_protocols(true);
6817 SessionDependencies session_deps;
6818
6819 HttpRequestInfo request;
6820 request.method = "GET";
6821 request.url = GURL("http://www.google.com/");
6822 request.load_flags = 0;
6823
6824 // The alternate protocol request will error out before we attempt to connect,
6825 // so only the standard HTTP request will try to connect.
6826 MockRead data_reads[] = {
6827 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6828 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066829 MockRead(ASYNC, OK),
[email protected]eb6234e2012-01-19 01:50:026830 };
6831 StaticSocketDataProvider data(
6832 data_reads, arraysize(data_reads), NULL, 0);
6833 session_deps.socket_factory.AddSocketDataProvider(&data);
6834
6835 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6836
6837 HttpServerProperties* http_server_properties =
6838 session->http_server_properties();
6839 const int kUnsafePort = 7;
6840 http_server_properties->SetAlternateProtocol(
6841 HostPortPair::FromURL(request.url),
6842 kUnsafePort,
6843 NPN_SPDY_2);
6844
6845 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6846 TestCompletionCallback callback;
6847
6848 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6849 EXPECT_EQ(ERR_IO_PENDING, rv);
6850 // The HTTP request should succeed.
6851 EXPECT_EQ(OK, callback.WaitForResult());
6852
6853 // Disable alternate protocol before the asserts.
6854 HttpStreamFactory::set_use_alternate_protocols(false);
6855
6856 const HttpResponseInfo* response = trans->GetResponseInfo();
6857 ASSERT_TRUE(response != NULL);
6858 ASSERT_TRUE(response->headers != NULL);
6859 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6860
6861 std::string response_data;
6862 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6863 EXPECT_EQ("hello world", response_data);
6864}
6865
[email protected]2ff8b312010-04-26 22:20:546866TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386867 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:036868 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:546869 SessionDependencies session_deps;
6870
6871 HttpRequestInfo request;
6872 request.method = "GET";
6873 request.url = GURL("http://www.google.com/");
6874 request.load_flags = 0;
6875
6876 MockRead data_reads[] = {
6877 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356878 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546879 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066880 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:546881 };
6882
6883 StaticSocketDataProvider first_transaction(
6884 data_reads, arraysize(data_reads), NULL, 0);
6885 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6886
[email protected]8ddf8322012-02-23 18:08:066887 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:516888 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2ff8b312010-04-26 22:20:546889 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6890
[email protected]2bd93022010-07-17 00:58:446891 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136892 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546893
[email protected]2bd93022010-07-17 00:58:446894 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6895 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546896 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136897 CreateMockRead(*resp),
6898 CreateMockRead(*data),
[email protected]8ddf8322012-02-23 18:08:066899 MockRead(ASYNC, 0, 0),
[email protected]2ff8b312010-04-26 22:20:546900 };
6901
[email protected]a1595312012-01-22 03:25:046902 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:546903 new DelayedSocketData(
6904 1, // wait for one write to finish before reading.
6905 spdy_reads, arraysize(spdy_reads),
6906 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:046907 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:546908
[email protected]d973e99a2012-02-17 21:02:366909 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:556910 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6911 NULL, 0, NULL, 0);
6912 hanging_non_alternate_protocol_socket.set_connect_data(
6913 never_finishing_connect);
6914 session_deps.socket_factory.AddSocketDataProvider(
6915 &hanging_non_alternate_protocol_socket);
6916
[email protected]49639fa2011-12-20 23:22:416917 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:546918
6919 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6920 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6921
[email protected]49639fa2011-12-20 23:22:416922 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546923 EXPECT_EQ(ERR_IO_PENDING, rv);
6924 EXPECT_EQ(OK, callback.WaitForResult());
6925
6926 const HttpResponseInfo* response = trans->GetResponseInfo();
6927 ASSERT_TRUE(response != NULL);
6928 ASSERT_TRUE(response->headers != NULL);
6929 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6930
6931 std::string response_data;
6932 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6933 EXPECT_EQ("hello world", response_data);
6934
6935 trans.reset(new HttpNetworkTransaction(session));
6936
[email protected]49639fa2011-12-20 23:22:416937 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546938 EXPECT_EQ(ERR_IO_PENDING, rv);
6939 EXPECT_EQ(OK, callback.WaitForResult());
6940
6941 response = trans->GetResponseInfo();
6942 ASSERT_TRUE(response != NULL);
6943 ASSERT_TRUE(response->headers != NULL);
6944 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536945 EXPECT_TRUE(response->was_fetched_via_spdy);
6946 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546947
6948 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6949 EXPECT_EQ("hello!", response_data);
6950
[email protected]ecf96e52012-03-03 00:43:036951 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:386952 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546953}
6954
[email protected]2d6728692011-03-12 01:39:556955TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6956 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:036957 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556958 SessionDependencies session_deps;
6959
6960 HttpRequestInfo request;
6961 request.method = "GET";
6962 request.url = GURL("http://www.google.com/");
6963 request.load_flags = 0;
6964
6965 MockRead data_reads[] = {
6966 MockRead("HTTP/1.1 200 OK\r\n"),
6967 MockRead(kAlternateProtocolHttpHeader),
6968 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:066969 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:556970 };
6971
6972 StaticSocketDataProvider first_transaction(
6973 data_reads, arraysize(data_reads), NULL, 0);
6974 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6975 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6976
[email protected]d973e99a2012-02-17 21:02:366977 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:556978 StaticSocketDataProvider hanging_socket(
6979 NULL, 0, NULL, 0);
6980 hanging_socket.set_connect_data(never_finishing_connect);
6981 // Socket 2 and 3 are the hanging Alternate-Protocol and
6982 // non-Alternate-Protocol jobs from the 2nd transaction.
6983 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6984 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6985
[email protected]8ddf8322012-02-23 18:08:066986 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:516987 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2d6728692011-03-12 01:39:556988 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6989
6990 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6991 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6992 MockWrite spdy_writes[] = {
6993 CreateMockWrite(*req1),
6994 CreateMockWrite(*req2),
6995 };
6996 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6997 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6998 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6999 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
7000 MockRead spdy_reads[] = {
7001 CreateMockRead(*resp1),
7002 CreateMockRead(*data1),
7003 CreateMockRead(*resp2),
7004 CreateMockRead(*data2),
[email protected]8ddf8322012-02-23 18:08:067005 MockRead(ASYNC, 0, 0),
[email protected]2d6728692011-03-12 01:39:557006 };
7007
[email protected]a1595312012-01-22 03:25:047008 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2d6728692011-03-12 01:39:557009 new DelayedSocketData(
7010 2, // wait for writes to finish before reading.
7011 spdy_reads, arraysize(spdy_reads),
7012 spdy_writes, arraysize(spdy_writes)));
7013 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]a1595312012-01-22 03:25:047014 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2d6728692011-03-12 01:39:557015
7016 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
7017 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
7018
7019 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]49639fa2011-12-20 23:22:417020 TestCompletionCallback callback1;
[email protected]2d6728692011-03-12 01:39:557021 HttpNetworkTransaction trans1(session);
7022
[email protected]49639fa2011-12-20 23:22:417023 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557024 EXPECT_EQ(ERR_IO_PENDING, rv);
7025 EXPECT_EQ(OK, callback1.WaitForResult());
7026
7027 const HttpResponseInfo* response = trans1.GetResponseInfo();
7028 ASSERT_TRUE(response != NULL);
7029 ASSERT_TRUE(response->headers != NULL);
7030 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7031
7032 std::string response_data;
7033 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
7034 EXPECT_EQ("hello world", response_data);
7035
[email protected]49639fa2011-12-20 23:22:417036 TestCompletionCallback callback2;
[email protected]2d6728692011-03-12 01:39:557037 HttpNetworkTransaction trans2(session);
[email protected]49639fa2011-12-20 23:22:417038 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557039 EXPECT_EQ(ERR_IO_PENDING, rv);
7040
[email protected]49639fa2011-12-20 23:22:417041 TestCompletionCallback callback3;
[email protected]2d6728692011-03-12 01:39:557042 HttpNetworkTransaction trans3(session);
[email protected]49639fa2011-12-20 23:22:417043 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557044 EXPECT_EQ(ERR_IO_PENDING, rv);
7045
7046 EXPECT_EQ(OK, callback2.WaitForResult());
7047 EXPECT_EQ(OK, callback3.WaitForResult());
7048
7049 response = trans2.GetResponseInfo();
7050 ASSERT_TRUE(response != NULL);
7051 ASSERT_TRUE(response->headers != NULL);
7052 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7053 EXPECT_TRUE(response->was_fetched_via_spdy);
7054 EXPECT_TRUE(response->was_npn_negotiated);
7055 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
7056 EXPECT_EQ("hello!", response_data);
7057
7058 response = trans3.GetResponseInfo();
7059 ASSERT_TRUE(response != NULL);
7060 ASSERT_TRUE(response->headers != NULL);
7061 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7062 EXPECT_TRUE(response->was_fetched_via_spdy);
7063 EXPECT_TRUE(response->was_npn_negotiated);
7064 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
7065 EXPECT_EQ("hello!", response_data);
7066
[email protected]ecf96e52012-03-03 00:43:037067 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557068 HttpStreamFactory::set_use_alternate_protocols(false);
7069}
7070
7071TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
7072 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:037073 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:557074 SessionDependencies session_deps;
7075
7076 HttpRequestInfo request;
7077 request.method = "GET";
7078 request.url = GURL("http://www.google.com/");
7079 request.load_flags = 0;
7080
7081 MockRead data_reads[] = {
7082 MockRead("HTTP/1.1 200 OK\r\n"),
7083 MockRead(kAlternateProtocolHttpHeader),
7084 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:067085 MockRead(ASYNC, OK),
[email protected]2d6728692011-03-12 01:39:557086 };
7087
7088 StaticSocketDataProvider first_transaction(
7089 data_reads, arraysize(data_reads), NULL, 0);
7090 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7091
[email protected]8ddf8322012-02-23 18:08:067092 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:517093 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2d6728692011-03-12 01:39:557094 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7095
[email protected]d973e99a2012-02-17 21:02:367096 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:557097 StaticSocketDataProvider hanging_alternate_protocol_socket(
7098 NULL, 0, NULL, 0);
7099 hanging_alternate_protocol_socket.set_connect_data(
7100 never_finishing_connect);
7101 session_deps.socket_factory.AddSocketDataProvider(
7102 &hanging_alternate_protocol_socket);
7103
7104 // 2nd request is just a copy of the first one, over HTTP again.
7105 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7106
[email protected]49639fa2011-12-20 23:22:417107 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:557108
7109 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7110 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7111
[email protected]49639fa2011-12-20 23:22:417112 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557113 EXPECT_EQ(ERR_IO_PENDING, rv);
7114 EXPECT_EQ(OK, callback.WaitForResult());
7115
7116 const HttpResponseInfo* response = trans->GetResponseInfo();
7117 ASSERT_TRUE(response != NULL);
7118 ASSERT_TRUE(response->headers != NULL);
7119 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7120
7121 std::string response_data;
7122 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7123 EXPECT_EQ("hello world", response_data);
7124
7125 trans.reset(new HttpNetworkTransaction(session));
7126
[email protected]49639fa2011-12-20 23:22:417127 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557128 EXPECT_EQ(ERR_IO_PENDING, rv);
7129 EXPECT_EQ(OK, callback.WaitForResult());
7130
7131 response = trans->GetResponseInfo();
7132 ASSERT_TRUE(response != NULL);
7133 ASSERT_TRUE(response->headers != NULL);
7134 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7135 EXPECT_FALSE(response->was_fetched_via_spdy);
7136 EXPECT_FALSE(response->was_npn_negotiated);
7137
7138 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7139 EXPECT_EQ("hello world", response_data);
7140
[email protected]ecf96e52012-03-03 00:43:037141 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557142 HttpStreamFactory::set_use_alternate_protocols(false);
7143}
7144
[email protected]631f1322010-04-30 17:59:117145class CapturingProxyResolver : public ProxyResolver {
7146 public:
7147 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7148 virtual ~CapturingProxyResolver() {}
7149
7150 virtual int GetProxyForURL(const GURL& url,
7151 ProxyInfo* results,
[email protected]235786812011-12-20 02:15:317152 const CompletionCallback& callback,
[email protected]631f1322010-04-30 17:59:117153 RequestHandle* request,
7154 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:407155 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7156 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:427157 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:117158 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:427159 return OK;
[email protected]631f1322010-04-30 17:59:117160 }
7161
7162 virtual void CancelRequest(RequestHandle request) {
7163 NOTREACHED();
7164 }
7165
[email protected]f2c971f2011-11-08 00:33:177166 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
7167 NOTREACHED();
7168 return LOAD_STATE_IDLE;
7169 }
7170
7171 virtual LoadState GetLoadStateThreadSafe(
7172 RequestHandle request) const OVERRIDE {
7173 NOTREACHED();
7174 return LOAD_STATE_IDLE;
7175 }
7176
[email protected]1e605472010-12-16 21:41:407177 virtual void CancelSetPacScript() {
7178 NOTREACHED();
7179 }
7180
[email protected]24476402010-07-20 20:55:177181 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]235786812011-12-20 02:15:317182 const CompletionCallback& /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:427183 return OK;
[email protected]631f1322010-04-30 17:59:117184 }
7185
[email protected]24476402010-07-20 20:55:177186 const std::vector<GURL>& resolved() const { return resolved_; }
7187
7188 private:
[email protected]631f1322010-04-30 17:59:117189 std::vector<GURL> resolved_;
7190
7191 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7192};
7193
[email protected]631f1322010-04-30 17:59:117194TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:387195 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:037196 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]631f1322010-04-30 17:59:117197
7198 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:427199 proxy_config.set_auto_detect(true);
7200 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:117201
[email protected]631f1322010-04-30 17:59:117202 CapturingProxyResolver* capturing_proxy_resolver =
7203 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:387204 SessionDependencies session_deps(new ProxyService(
7205 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7206 NULL));
[email protected]631f1322010-04-30 17:59:117207
7208 HttpRequestInfo request;
7209 request.method = "GET";
7210 request.url = GURL("http://www.google.com/");
7211 request.load_flags = 0;
7212
7213 MockRead data_reads[] = {
7214 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357215 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:117216 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:067217 MockRead(ASYNC, OK),
[email protected]631f1322010-04-30 17:59:117218 };
7219
7220 StaticSocketDataProvider first_transaction(
7221 data_reads, arraysize(data_reads), NULL, 0);
7222 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7223
[email protected]8ddf8322012-02-23 18:08:067224 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:517225 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]631f1322010-04-30 17:59:117226 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7227
[email protected]2bd93022010-07-17 00:58:447228 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:117229 MockWrite spdy_writes[] = {
7230 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7231 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:427232 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:137233 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:117234 };
7235
[email protected]d911f1b2010-05-05 22:39:427236 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7237
[email protected]2bd93022010-07-17 00:58:447238 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7239 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:117240 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:067241 MockRead(ASYNC, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:137242 CreateMockRead(*resp.get(), 4), // 2, 4
7243 CreateMockRead(*data.get(), 4), // 5
[email protected]8ddf8322012-02-23 18:08:067244 MockRead(ASYNC, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:117245 };
7246
[email protected]a1595312012-01-22 03:25:047247 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d911f1b2010-05-05 22:39:427248 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:117249 spdy_reads, arraysize(spdy_reads),
7250 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047251 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]631f1322010-04-30 17:59:117252
[email protected]d973e99a2012-02-17 21:02:367253 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:557254 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7255 NULL, 0, NULL, 0);
7256 hanging_non_alternate_protocol_socket.set_connect_data(
7257 never_finishing_connect);
7258 session_deps.socket_factory.AddSocketDataProvider(
7259 &hanging_non_alternate_protocol_socket);
7260
[email protected]49639fa2011-12-20 23:22:417261 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:117262
7263 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7264 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7265
[email protected]49639fa2011-12-20 23:22:417266 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117267 EXPECT_EQ(ERR_IO_PENDING, rv);
7268 EXPECT_EQ(OK, callback.WaitForResult());
7269
7270 const HttpResponseInfo* response = trans->GetResponseInfo();
7271 ASSERT_TRUE(response != NULL);
7272 ASSERT_TRUE(response->headers != NULL);
7273 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537274 EXPECT_FALSE(response->was_fetched_via_spdy);
7275 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117276
7277 std::string response_data;
7278 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7279 EXPECT_EQ("hello world", response_data);
7280
7281 trans.reset(new HttpNetworkTransaction(session));
7282
[email protected]49639fa2011-12-20 23:22:417283 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117284 EXPECT_EQ(ERR_IO_PENDING, rv);
7285 EXPECT_EQ(OK, callback.WaitForResult());
7286
7287 response = trans->GetResponseInfo();
7288 ASSERT_TRUE(response != NULL);
7289 ASSERT_TRUE(response->headers != NULL);
7290 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537291 EXPECT_TRUE(response->was_fetched_via_spdy);
7292 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117293
7294 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7295 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557296 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427297 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117298 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427299 EXPECT_EQ("https://www.google.com/",
7300 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117301
[email protected]ecf96e52012-03-03 00:43:037302 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387303 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117304}
[email protected]631f1322010-04-30 17:59:117305
[email protected]2ff8b312010-04-26 22:20:547306TEST_F(HttpNetworkTransactionTest,
7307 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387308 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:037309 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:547310 SessionDependencies session_deps;
7311
7312 HttpRequestInfo request;
7313 request.method = "GET";
7314 request.url = GURL("http://www.google.com/");
7315 request.load_flags = 0;
7316
7317 MockRead data_reads[] = {
7318 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357319 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547320 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:067321 MockRead(ASYNC, OK),
[email protected]2ff8b312010-04-26 22:20:547322 };
7323
7324 StaticSocketDataProvider first_transaction(
7325 data_reads, arraysize(data_reads), NULL, 0);
7326 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7327
[email protected]8ddf8322012-02-23 18:08:067328 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:517329 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]2ff8b312010-04-26 22:20:547330 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537331 // Make sure we use ssl for spdy here.
7332 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547333
[email protected]2bd93022010-07-17 00:58:447334 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137335 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547336
[email protected]2bd93022010-07-17 00:58:447337 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7338 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547339 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137340 CreateMockRead(*resp),
7341 CreateMockRead(*data),
[email protected]8ddf8322012-02-23 18:08:067342 MockRead(ASYNC, 0, 0),
[email protected]2ff8b312010-04-26 22:20:547343 };
7344
[email protected]a1595312012-01-22 03:25:047345 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:547346 new DelayedSocketData(
7347 1, // wait for one write to finish before reading.
7348 spdy_reads, arraysize(spdy_reads),
7349 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047350 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:547351
[email protected]83039bb2011-12-09 18:43:557352 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:547353
7354 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7355
7356 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7357
[email protected]49639fa2011-12-20 23:22:417358 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547359 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417360 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547361
7362 const HttpResponseInfo* response = trans->GetResponseInfo();
7363 ASSERT_TRUE(response != NULL);
7364 ASSERT_TRUE(response->headers != NULL);
7365 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7366
7367 std::string response_data;
7368 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7369 EXPECT_EQ("hello world", response_data);
7370
7371 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387372 HostPortPair host_port_pair("www.google.com", 443);
7373 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547374 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317375 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287376 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:297377 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]02b0c342010-09-25 21:09:387378
7379 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7380 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287381 connection->Init(host_port_pair.ToString(),
7382 transport_params,
7383 LOWEST,
[email protected]6ecf2b92011-12-15 01:14:527384 callback.callback(),
[email protected]a42dbd142011-11-17 16:42:027385 session->GetTransportSocketPool(),
[email protected]02b0c342010-09-25 21:09:387386 BoundNetLog()));
[email protected]6ecf2b92011-12-15 01:14:527387 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]02b0c342010-09-25 21:09:387388
7389 SSLConfig ssl_config;
7390 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347391 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177392 SSLClientSocketContext context;
7393 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347394 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7395 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177396 NULL /* ssl_host_info */, context));
[email protected]83039bb2011-12-09 18:43:557397 EXPECT_EQ(ERR_IO_PENDING,
7398 ssl_connection->socket()->Connect(callback.callback()));
[email protected]02b0c342010-09-25 21:09:387399 EXPECT_EQ(OK, callback.WaitForResult());
7400
[email protected]9e1bdd32011-02-03 21:48:347401 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387402 true, OK));
7403
[email protected]2ff8b312010-04-26 22:20:547404 trans.reset(new HttpNetworkTransaction(session));
7405
[email protected]49639fa2011-12-20 23:22:417406 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547407 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417408 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547409
7410 response = trans->GetResponseInfo();
7411 ASSERT_TRUE(response != NULL);
7412 ASSERT_TRUE(response->headers != NULL);
7413 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537414 EXPECT_TRUE(response->was_fetched_via_spdy);
7415 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547416
7417 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7418 EXPECT_EQ("hello!", response_data);
7419
[email protected]ecf96e52012-03-03 00:43:037420 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387421 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427422}
7423
[email protected]044de0642010-06-17 10:42:157424// GenerateAuthToken is a mighty big test.
7425// It tests all permutation of GenerateAuthToken behavior:
7426// - Synchronous and Asynchronous completion.
7427// - OK or error on completion.
7428// - Direct connection, non-authenticating proxy, and authenticating proxy.
7429// - HTTP or HTTPS backend (to include proxy tunneling).
7430// - Non-authenticating and authenticating backend.
7431//
[email protected]fe3b7dc2012-02-03 19:52:097432// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:157433// problems generating an auth token for an authenticating proxy, we don't
7434// need to test all permutations of the backend server).
7435//
7436// The test proceeds by going over each of the configuration cases, and
7437// potentially running up to three rounds in each of the tests. The TestConfig
7438// specifies both the configuration for the test as well as the expectations
7439// for the results.
7440TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507441 static const char kServer[] = "http://www.example.com";
7442 static const char kSecureServer[] = "https://www.example.com";
7443 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157444 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7445
7446 enum AuthTiming {
7447 AUTH_NONE,
7448 AUTH_SYNC,
7449 AUTH_ASYNC,
7450 };
7451
7452 const MockWrite kGet(
7453 "GET / HTTP/1.1\r\n"
7454 "Host: www.example.com\r\n"
7455 "Connection: keep-alive\r\n\r\n");
7456 const MockWrite kGetProxy(
7457 "GET http://www.example.com/ HTTP/1.1\r\n"
7458 "Host: www.example.com\r\n"
7459 "Proxy-Connection: keep-alive\r\n\r\n");
7460 const MockWrite kGetAuth(
7461 "GET / HTTP/1.1\r\n"
7462 "Host: www.example.com\r\n"
7463 "Connection: keep-alive\r\n"
7464 "Authorization: auth_token\r\n\r\n");
7465 const MockWrite kGetProxyAuth(
7466 "GET http://www.example.com/ HTTP/1.1\r\n"
7467 "Host: www.example.com\r\n"
7468 "Proxy-Connection: keep-alive\r\n"
7469 "Proxy-Authorization: auth_token\r\n\r\n");
7470 const MockWrite kGetAuthThroughProxy(
7471 "GET http://www.example.com/ HTTP/1.1\r\n"
7472 "Host: www.example.com\r\n"
7473 "Proxy-Connection: keep-alive\r\n"
7474 "Authorization: auth_token\r\n\r\n");
7475 const MockWrite kGetAuthWithProxyAuth(
7476 "GET http://www.example.com/ HTTP/1.1\r\n"
7477 "Host: www.example.com\r\n"
7478 "Proxy-Connection: keep-alive\r\n"
7479 "Proxy-Authorization: auth_token\r\n"
7480 "Authorization: auth_token\r\n\r\n");
7481 const MockWrite kConnect(
7482 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7483 "Host: www.example.com\r\n"
7484 "Proxy-Connection: keep-alive\r\n\r\n");
7485 const MockWrite kConnectProxyAuth(
7486 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7487 "Host: www.example.com\r\n"
7488 "Proxy-Connection: keep-alive\r\n"
7489 "Proxy-Authorization: auth_token\r\n\r\n");
7490
7491 const MockRead kSuccess(
7492 "HTTP/1.1 200 OK\r\n"
7493 "Content-Type: text/html; charset=iso-8859-1\r\n"
7494 "Content-Length: 3\r\n\r\n"
7495 "Yes");
7496 const MockRead kFailure(
7497 "Should not be called.");
7498 const MockRead kServerChallenge(
7499 "HTTP/1.1 401 Unauthorized\r\n"
7500 "WWW-Authenticate: Mock realm=server\r\n"
7501 "Content-Type: text/html; charset=iso-8859-1\r\n"
7502 "Content-Length: 14\r\n\r\n"
7503 "Unauthorized\r\n");
7504 const MockRead kProxyChallenge(
7505 "HTTP/1.1 407 Unauthorized\r\n"
7506 "Proxy-Authenticate: Mock realm=proxy\r\n"
7507 "Proxy-Connection: close\r\n"
7508 "Content-Type: text/html; charset=iso-8859-1\r\n"
7509 "Content-Length: 14\r\n\r\n"
7510 "Unauthorized\r\n");
7511 const MockRead kProxyConnected(
7512 "HTTP/1.1 200 Connection Established\r\n\r\n");
7513
7514 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7515 // no constructors, but the C++ compiler on Windows warns about
7516 // unspecified data in compound literals. So, moved to using constructors,
7517 // and TestRound's created with the default constructor should not be used.
7518 struct TestRound {
7519 TestRound()
7520 : expected_rv(ERR_UNEXPECTED),
7521 extra_write(NULL),
7522 extra_read(NULL) {
7523 }
7524 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7525 int expected_rv_arg)
7526 : write(write_arg),
7527 read(read_arg),
7528 expected_rv(expected_rv_arg),
7529 extra_write(NULL),
7530 extra_read(NULL) {
7531 }
7532 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7533 int expected_rv_arg, const MockWrite* extra_write_arg,
7534 const MockWrite* extra_read_arg)
7535 : write(write_arg),
7536 read(read_arg),
7537 expected_rv(expected_rv_arg),
7538 extra_write(extra_write_arg),
7539 extra_read(extra_read_arg) {
7540 }
7541 MockWrite write;
7542 MockRead read;
7543 int expected_rv;
7544 const MockWrite* extra_write;
7545 const MockRead* extra_read;
7546 };
7547
7548 static const int kNoSSL = 500;
7549
7550 struct TestConfig {
7551 const char* proxy_url;
7552 AuthTiming proxy_auth_timing;
7553 int proxy_auth_rv;
7554 const char* server_url;
7555 AuthTiming server_auth_timing;
7556 int server_auth_rv;
7557 int num_auth_rounds;
7558 int first_ssl_round;
7559 TestRound rounds[3];
7560 } test_configs[] = {
7561 // Non-authenticating HTTP server with a direct connection.
7562 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7563 { TestRound(kGet, kSuccess, OK)}},
7564 // Authenticating HTTP server with a direct connection.
7565 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7566 { TestRound(kGet, kServerChallenge, OK),
7567 TestRound(kGetAuth, kSuccess, OK)}},
7568 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7569 { TestRound(kGet, kServerChallenge, OK),
7570 TestRound(kGetAuth, kFailure, kAuthErr)}},
7571 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7572 { TestRound(kGet, kServerChallenge, OK),
7573 TestRound(kGetAuth, kSuccess, OK)}},
7574 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7575 { TestRound(kGet, kServerChallenge, OK),
7576 TestRound(kGetAuth, kFailure, kAuthErr)}},
7577 // Non-authenticating HTTP server through a non-authenticating proxy.
7578 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7579 { TestRound(kGetProxy, kSuccess, OK)}},
7580 // Authenticating HTTP server through a non-authenticating proxy.
7581 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7582 { TestRound(kGetProxy, kServerChallenge, OK),
7583 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7584 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7585 { TestRound(kGetProxy, kServerChallenge, OK),
7586 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7587 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7588 { TestRound(kGetProxy, kServerChallenge, OK),
7589 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7590 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7591 { TestRound(kGetProxy, kServerChallenge, OK),
7592 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7593 // Non-authenticating HTTP server through an authenticating proxy.
7594 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7595 { TestRound(kGetProxy, kProxyChallenge, OK),
7596 TestRound(kGetProxyAuth, kSuccess, OK)}},
7597 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7598 { TestRound(kGetProxy, kProxyChallenge, OK),
7599 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7600 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7601 { TestRound(kGetProxy, kProxyChallenge, OK),
7602 TestRound(kGetProxyAuth, kSuccess, OK)}},
7603 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7604 { TestRound(kGetProxy, kProxyChallenge, OK),
7605 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7606 // Authenticating HTTP server through an authenticating proxy.
7607 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7608 { TestRound(kGetProxy, kProxyChallenge, OK),
7609 TestRound(kGetProxyAuth, kServerChallenge, OK),
7610 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7611 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7612 { TestRound(kGetProxy, kProxyChallenge, OK),
7613 TestRound(kGetProxyAuth, kServerChallenge, OK),
7614 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7615 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7616 { TestRound(kGetProxy, kProxyChallenge, OK),
7617 TestRound(kGetProxyAuth, kServerChallenge, OK),
7618 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7619 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7620 { TestRound(kGetProxy, kProxyChallenge, OK),
7621 TestRound(kGetProxyAuth, kServerChallenge, OK),
7622 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7623 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7624 { TestRound(kGetProxy, kProxyChallenge, OK),
7625 TestRound(kGetProxyAuth, kServerChallenge, OK),
7626 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7627 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7628 { TestRound(kGetProxy, kProxyChallenge, OK),
7629 TestRound(kGetProxyAuth, kServerChallenge, OK),
7630 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7631 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7632 { TestRound(kGetProxy, kProxyChallenge, OK),
7633 TestRound(kGetProxyAuth, kServerChallenge, OK),
7634 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7635 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7636 { TestRound(kGetProxy, kProxyChallenge, OK),
7637 TestRound(kGetProxyAuth, kServerChallenge, OK),
7638 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7639 // Non-authenticating HTTPS server with a direct connection.
7640 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7641 { TestRound(kGet, kSuccess, OK)}},
7642 // Authenticating HTTPS server with a direct connection.
7643 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7644 { TestRound(kGet, kServerChallenge, OK),
7645 TestRound(kGetAuth, kSuccess, OK)}},
7646 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7647 { TestRound(kGet, kServerChallenge, OK),
7648 TestRound(kGetAuth, kFailure, kAuthErr)}},
7649 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7650 { TestRound(kGet, kServerChallenge, OK),
7651 TestRound(kGetAuth, kSuccess, OK)}},
7652 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7653 { TestRound(kGet, kServerChallenge, OK),
7654 TestRound(kGetAuth, kFailure, kAuthErr)}},
7655 // Non-authenticating HTTPS server with a non-authenticating proxy.
7656 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7657 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7658 // Authenticating HTTPS server through a non-authenticating proxy.
7659 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7660 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7661 TestRound(kGetAuth, kSuccess, OK)}},
7662 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7663 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7664 TestRound(kGetAuth, kFailure, kAuthErr)}},
7665 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7666 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7667 TestRound(kGetAuth, kSuccess, OK)}},
7668 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7669 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7670 TestRound(kGetAuth, kFailure, kAuthErr)}},
7671 // Non-Authenticating HTTPS server through an authenticating proxy.
7672 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7673 { TestRound(kConnect, kProxyChallenge, OK),
7674 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7675 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7676 { TestRound(kConnect, kProxyChallenge, OK),
7677 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7678 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7679 { TestRound(kConnect, kProxyChallenge, OK),
7680 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7681 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7682 { TestRound(kConnect, kProxyChallenge, OK),
7683 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7684 // Authenticating HTTPS server through an authenticating proxy.
7685 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7686 { TestRound(kConnect, kProxyChallenge, OK),
7687 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7688 &kGet, &kServerChallenge),
7689 TestRound(kGetAuth, kSuccess, OK)}},
7690 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7691 { TestRound(kConnect, kProxyChallenge, OK),
7692 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7693 &kGet, &kServerChallenge),
7694 TestRound(kGetAuth, kFailure, kAuthErr)}},
7695 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7696 { TestRound(kConnect, kProxyChallenge, OK),
7697 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7698 &kGet, &kServerChallenge),
7699 TestRound(kGetAuth, kSuccess, OK)}},
7700 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7701 { TestRound(kConnect, kProxyChallenge, OK),
7702 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7703 &kGet, &kServerChallenge),
7704 TestRound(kGetAuth, kFailure, kAuthErr)}},
7705 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7706 { TestRound(kConnect, kProxyChallenge, OK),
7707 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7708 &kGet, &kServerChallenge),
7709 TestRound(kGetAuth, kSuccess, OK)}},
7710 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7711 { TestRound(kConnect, kProxyChallenge, OK),
7712 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7713 &kGet, &kServerChallenge),
7714 TestRound(kGetAuth, kFailure, kAuthErr)}},
7715 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7716 { TestRound(kConnect, kProxyChallenge, OK),
7717 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7718 &kGet, &kServerChallenge),
7719 TestRound(kGetAuth, kSuccess, OK)}},
7720 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7721 { TestRound(kConnect, kProxyChallenge, OK),
7722 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7723 &kGet, &kServerChallenge),
7724 TestRound(kGetAuth, kFailure, kAuthErr)}},
7725 };
7726
7727 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157728 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087729 HttpAuthHandlerMock::Factory* auth_factory(
7730 new HttpAuthHandlerMock::Factory());
7731 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157732 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267733
7734 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157735 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087736 for (int n = 0; n < 2; n++) {
7737 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7738 std::string auth_challenge = "Mock realm=proxy";
7739 GURL origin(test_config.proxy_url);
7740 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7741 auth_challenge.end());
7742 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7743 origin, BoundNetLog());
7744 auth_handler->SetGenerateExpectation(
7745 test_config.proxy_auth_timing == AUTH_ASYNC,
7746 test_config.proxy_auth_rv);
7747 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7748 }
[email protected]044de0642010-06-17 10:42:157749 }
7750 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007751 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157752 std::string auth_challenge = "Mock realm=server";
7753 GURL origin(test_config.server_url);
7754 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7755 auth_challenge.end());
7756 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7757 origin, BoundNetLog());
7758 auth_handler->SetGenerateExpectation(
7759 test_config.server_auth_timing == AUTH_ASYNC,
7760 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087761 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157762 }
7763 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127764 session_deps.proxy_service.reset(
7765 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157766 } else {
[email protected]6104ea5d2011-04-27 21:37:127767 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157768 }
7769
7770 HttpRequestInfo request;
7771 request.method = "GET";
7772 request.url = GURL(test_config.server_url);
7773 request.load_flags = 0;
7774
[email protected]0b0bf032010-09-21 18:08:507775 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7776 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157777
7778 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7779 const TestRound& read_write_round = test_config.rounds[round];
7780
7781 // Set up expected reads and writes.
7782 MockRead reads[2];
7783 reads[0] = read_write_round.read;
7784 size_t length_reads = 1;
7785 if (read_write_round.extra_read) {
7786 reads[1] = *read_write_round.extra_read;
7787 length_reads = 2;
7788 }
7789
7790 MockWrite writes[2];
7791 writes[0] = read_write_round.write;
7792 size_t length_writes = 1;
7793 if (read_write_round.extra_write) {
7794 writes[1] = *read_write_round.extra_write;
7795 length_writes = 2;
7796 }
7797 StaticSocketDataProvider data_provider(
7798 reads, length_reads, writes, length_writes);
7799 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7800
7801 // Add an SSL sequence if necessary.
[email protected]8ddf8322012-02-23 18:08:067802 SSLSocketDataProvider ssl_socket_data_provider(SYNCHRONOUS, OK);
[email protected]044de0642010-06-17 10:42:157803 if (round >= test_config.first_ssl_round)
7804 session_deps.socket_factory.AddSSLSocketDataProvider(
7805 &ssl_socket_data_provider);
7806
7807 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:417808 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:157809 int rv;
7810 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:417811 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:157812 } else {
[email protected]49639fa2011-12-20 23:22:417813 rv = trans.RestartWithAuth(
7814 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:157815 }
7816 if (rv == ERR_IO_PENDING)
7817 rv = callback.WaitForResult();
7818
7819 // Compare results with expected data.
7820 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507821 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157822 if (read_write_round.expected_rv == OK) {
[email protected]fe2255a2011-09-20 19:37:507823 ASSERT_TRUE(response != NULL);
[email protected]044de0642010-06-17 10:42:157824 } else {
7825 EXPECT_TRUE(response == NULL);
7826 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7827 continue;
7828 }
7829 if (round + 1 < test_config.num_auth_rounds) {
7830 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7831 } else {
7832 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7833 }
7834 }
[email protected]e5ae96a2010-04-14 20:12:457835 }
7836}
7837
[email protected]c871bce92010-07-15 21:51:147838TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7839 // Do multi-round authentication and make sure it works correctly.
7840 SessionDependencies session_deps;
7841 HttpAuthHandlerMock::Factory* auth_factory(
7842 new HttpAuthHandlerMock::Factory());
7843 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127844 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147845 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7846 session_deps.host_resolver->set_synchronous_mode(true);
7847
7848 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7849 auth_handler->set_connection_based(true);
7850 std::string auth_challenge = "Mock realm=server";
7851 GURL origin("http://www.example.com");
7852 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7853 auth_challenge.end());
7854 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7855 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087856 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147857
[email protected]c871bce92010-07-15 21:51:147858 int rv = OK;
7859 const HttpResponseInfo* response = NULL;
7860 HttpRequestInfo request;
7861 request.method = "GET";
7862 request.url = origin;
7863 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277864
7865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107866
7867 // Use a TCP Socket Pool with only one connection per group. This is used
7868 // to validate that the TCP socket is not released to the pool between
7869 // each round of multi-round authentication.
7870 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287871 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7872 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107873 50, // Max sockets for pool
7874 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287875 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107876 session_deps.host_resolver.get(),
7877 &session_deps.socket_factory,
7878 session_deps.net_log);
[email protected]a42dbd142011-11-17 16:42:027879 MockClientSocketPoolManager* mock_pool_manager =
7880 new MockClientSocketPoolManager;
7881 mock_pool_manager->SetTransportSocketPool(transport_pool);
7882 session_peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]7ef4cbbb2011-02-06 11:19:107883
[email protected]cb9bf6ca2011-01-28 13:15:277884 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417885 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:147886
7887 const MockWrite kGet(
7888 "GET / HTTP/1.1\r\n"
7889 "Host: www.example.com\r\n"
7890 "Connection: keep-alive\r\n\r\n");
7891 const MockWrite kGetAuth(
7892 "GET / HTTP/1.1\r\n"
7893 "Host: www.example.com\r\n"
7894 "Connection: keep-alive\r\n"
7895 "Authorization: auth_token\r\n\r\n");
7896
7897 const MockRead kServerChallenge(
7898 "HTTP/1.1 401 Unauthorized\r\n"
7899 "WWW-Authenticate: Mock realm=server\r\n"
7900 "Content-Type: text/html; charset=iso-8859-1\r\n"
7901 "Content-Length: 14\r\n\r\n"
7902 "Unauthorized\r\n");
7903 const MockRead kSuccess(
7904 "HTTP/1.1 200 OK\r\n"
7905 "Content-Type: text/html; charset=iso-8859-1\r\n"
7906 "Content-Length: 3\r\n\r\n"
7907 "Yes");
7908
7909 MockWrite writes[] = {
7910 // First round
7911 kGet,
7912 // Second round
7913 kGetAuth,
7914 // Third round
7915 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307916 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107917 kGetAuth,
7918 // Competing request
7919 kGet,
[email protected]c871bce92010-07-15 21:51:147920 };
7921 MockRead reads[] = {
7922 // First round
7923 kServerChallenge,
7924 // Second round
7925 kServerChallenge,
7926 // Third round
[email protected]eca50e122010-09-11 14:03:307927 kServerChallenge,
7928 // Fourth round
[email protected]c871bce92010-07-15 21:51:147929 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107930 // Competing response
7931 kSuccess,
[email protected]c871bce92010-07-15 21:51:147932 };
7933 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7934 writes, arraysize(writes));
7935 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7936
[email protected]7ef4cbbb2011-02-06 11:19:107937 const char* const kSocketGroup = "www.example.com:80";
7938
7939 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147940 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417941 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]c871bce92010-07-15 21:51:147942 if (rv == ERR_IO_PENDING)
7943 rv = callback.WaitForResult();
7944 EXPECT_EQ(OK, rv);
7945 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507946 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147947 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287948 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147949
[email protected]7ef4cbbb2011-02-06 11:19:107950 // In between rounds, another request comes in for the same domain.
7951 // It should not be able to grab the TCP socket that trans has already
7952 // claimed.
7953 scoped_ptr<HttpTransaction> trans_compete(
7954 new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417955 TestCompletionCallback callback_compete;
7956 rv = trans_compete->Start(
7957 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:107958 EXPECT_EQ(ERR_IO_PENDING, rv);
7959 // callback_compete.WaitForResult at this point would stall forever,
7960 // since the HttpNetworkTransaction does not release the request back to
7961 // the pool until after authentication completes.
7962
7963 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147964 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417965 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:147966 if (rv == ERR_IO_PENDING)
7967 rv = callback.WaitForResult();
7968 EXPECT_EQ(OK, rv);
7969 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507970 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147971 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287972 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147973
[email protected]7ef4cbbb2011-02-06 11:19:107974 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147975 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417976 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:147977 if (rv == ERR_IO_PENDING)
7978 rv = callback.WaitForResult();
7979 EXPECT_EQ(OK, rv);
7980 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507981 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147982 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287983 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307984
[email protected]7ef4cbbb2011-02-06 11:19:107985 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307986 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:417987 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:307988 if (rv == ERR_IO_PENDING)
7989 rv = callback.WaitForResult();
7990 EXPECT_EQ(OK, rv);
7991 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507992 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:307993 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287994 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107995
7996 // Read the body since the fourth round was successful. This will also
7997 // release the socket back to the pool.
7998 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]49639fa2011-12-20 23:22:417999 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108000 if (rv == ERR_IO_PENDING)
8001 rv = callback.WaitForResult();
8002 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:418003 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108004 EXPECT_EQ(0, rv);
8005 // There are still 0 idle sockets, since the trans_compete transaction
8006 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:288007 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:108008
8009 // The competing request can now finish. Wait for the headers and then
8010 // read the body.
8011 rv = callback_compete.WaitForResult();
8012 EXPECT_EQ(OK, rv);
[email protected]49639fa2011-12-20 23:22:418013 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108014 if (rv == ERR_IO_PENDING)
8015 rv = callback.WaitForResult();
8016 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:418017 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108018 EXPECT_EQ(0, rv);
8019
8020 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:288021 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:148022}
8023
[email protected]aeaca1f2010-04-20 22:05:218024class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
8025 public:
[email protected]06650c52010-06-03 00:49:178026 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:218027 : fail_all_(fail_all) {
8028 }
8029
8030 virtual MockRead GetNextRead() {
8031 if (fail_all_)
[email protected]8ddf8322012-02-23 18:08:068032 return MockRead(SYNCHRONOUS, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:218033
[email protected]8ddf8322012-02-23 18:08:068034 return MockRead(SYNCHRONOUS,
[email protected]aeaca1f2010-04-20 22:05:218035 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
8036 }
8037
8038 virtual MockWriteResult OnWrite(const std::string& data) {
[email protected]8ddf8322012-02-23 18:08:068039 return MockWriteResult(SYNCHRONOUS /* async */, data.size());
[email protected]aeaca1f2010-04-20 22:05:218040 }
8041
8042 void Reset() {
8043 }
8044
8045 private:
8046 const bool fail_all_;
8047};
8048
8049// Test that we restart a connection when we see a decompression failure from
8050// the peer during the handshake. (In the real world we'll restart with SSLv3
8051// and we won't offer DEFLATE in that case.)
8052TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
8053 HttpRequestInfo request;
8054 request.method = "GET";
8055 request.url = GURL("https://tlsdecompressionfailure.example.com/");
8056 request.load_flags = 0;
8057
8058 SessionDependencies session_deps;
8059 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8060 false /* fail all reads */);
8061 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8062 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]8ddf8322012-02-23 18:08:068063 SYNCHRONOUS, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
8064 SSLSocketDataProvider ssl_socket_data_provider2(SYNCHRONOUS, OK);
[email protected]aeaca1f2010-04-20 22:05:218065 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8066 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8067 session_deps.socket_factory.AddSSLSocketDataProvider(
8068 &ssl_socket_data_provider1);
8069 session_deps.socket_factory.AddSSLSocketDataProvider(
8070 &ssl_socket_data_provider2);
8071
[email protected]e60e47a2010-07-14 03:37:188072 // Work around http://crbug.com/37454
8073 StaticSocketDataProvider bug37454_connection;
[email protected]d973e99a2012-02-17 21:02:368074 bug37454_connection.set_connect_data(MockConnect(ASYNC, ERR_UNEXPECTED));
[email protected]e60e47a2010-07-14 03:37:188075 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
8076
[email protected]aeaca1f2010-04-20 22:05:218077 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8078 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418079 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218080
[email protected]49639fa2011-12-20 23:22:418081 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218082 EXPECT_EQ(ERR_IO_PENDING, rv);
8083 EXPECT_EQ(OK, callback.WaitForResult());
8084
8085 const HttpResponseInfo* response = trans->GetResponseInfo();
8086 ASSERT_TRUE(response != NULL);
8087 ASSERT_TRUE(response->headers != NULL);
8088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8089
8090 std::string response_data;
8091 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8092 EXPECT_EQ("ok.", response_data);
8093}
8094
8095// Test that we restart a connection if we get a decompression failure from the
8096// peer while reading the first bytes from the connection. This occurs when the
8097// peer cannot handle DEFLATE but we're using False Start, so we don't notice
8098// in the handshake.
8099TEST_F(HttpNetworkTransactionTest,
8100 RestartAfterTLSDecompressionFailureWithFalseStart) {
8101 HttpRequestInfo request;
8102 request.method = "GET";
8103 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
8104 request.load_flags = 0;
8105
8106 SessionDependencies session_deps;
8107 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8108 true /* fail all reads */);
8109 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
[email protected]8ddf8322012-02-23 18:08:068110 SSLSocketDataProvider ssl_socket_data_provider1(SYNCHRONOUS, OK);
8111 SSLSocketDataProvider ssl_socket_data_provider2(SYNCHRONOUS, OK);
[email protected]aeaca1f2010-04-20 22:05:218112 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8113 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8114 session_deps.socket_factory.AddSSLSocketDataProvider(
8115 &ssl_socket_data_provider1);
8116 session_deps.socket_factory.AddSSLSocketDataProvider(
8117 &ssl_socket_data_provider2);
8118
8119 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8120 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418121 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218122
[email protected]49639fa2011-12-20 23:22:418123 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218124 EXPECT_EQ(ERR_IO_PENDING, rv);
8125 EXPECT_EQ(OK, callback.WaitForResult());
8126
8127 const HttpResponseInfo* response = trans->GetResponseInfo();
8128 ASSERT_TRUE(response != NULL);
8129 ASSERT_TRUE(response->headers != NULL);
8130 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8131
8132 std::string response_data;
8133 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8134 EXPECT_EQ("ok.", response_data);
8135}
8136
[email protected]65041fa2010-05-21 06:56:538137// This tests the case that a request is issued via http instead of spdy after
8138// npn is negotiated.
8139TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:388140 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:038141 HttpStreamFactory::SetNextProtos(
[email protected]5285d972011-10-18 18:56:348142 MakeNextProtos("http/1.1", "http1.1", NULL));
[email protected]65041fa2010-05-21 06:56:538143 SessionDependencies session_deps;
8144 HttpRequestInfo request;
8145 request.method = "GET";
8146 request.url = GURL("https://www.google.com/");
8147 request.load_flags = 0;
8148
8149 MockWrite data_writes[] = {
8150 MockWrite("GET / HTTP/1.1\r\n"
8151 "Host: www.google.com\r\n"
8152 "Connection: keep-alive\r\n\r\n"),
8153 };
8154
8155 MockRead data_reads[] = {
8156 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:358157 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:538158 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:068159 MockRead(SYNCHRONOUS, OK),
[email protected]65041fa2010-05-21 06:56:538160 };
8161
[email protected]8ddf8322012-02-23 18:08:068162 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]65041fa2010-05-21 06:56:538163 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8164 ssl.next_proto = "http/1.1";
[email protected]c30bcce2011-12-20 17:50:518165 ssl.protocol_negotiated = SSLClientSocket::kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:538166
8167 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8168
8169 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8170 data_writes, arraysize(data_writes));
8171 session_deps.socket_factory.AddSocketDataProvider(&data);
8172
[email protected]49639fa2011-12-20 23:22:418173 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:538174
8175 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8176 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8177
[email protected]49639fa2011-12-20 23:22:418178 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:538179
8180 EXPECT_EQ(ERR_IO_PENDING, rv);
8181 EXPECT_EQ(OK, callback.WaitForResult());
8182
8183 const HttpResponseInfo* response = trans->GetResponseInfo();
8184 ASSERT_TRUE(response != NULL);
8185 ASSERT_TRUE(response->headers != NULL);
8186 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8187
8188 std::string response_data;
8189 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8190 EXPECT_EQ("hello world", response_data);
8191
8192 EXPECT_FALSE(response->was_fetched_via_spdy);
8193 EXPECT_TRUE(response->was_npn_negotiated);
8194
[email protected]ecf96e52012-03-03 00:43:038195 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388196 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:538197}
[email protected]26ef6582010-06-24 02:30:478198
8199TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8200 // Simulate the SSL handshake completing with an NPN negotiation
8201 // followed by an immediate server closing of the socket.
8202 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:388203 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:038204 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]26ef6582010-06-24 02:30:478205 SessionDependencies session_deps;
8206
8207 HttpRequestInfo request;
8208 request.method = "GET";
8209 request.url = GURL("https://www.google.com/");
8210 request.load_flags = 0;
8211
[email protected]8ddf8322012-02-23 18:08:068212 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]e58c1b82012-02-22 23:07:518213 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]26ef6582010-06-24 02:30:478214 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8215
[email protected]2bd93022010-07-17 00:58:448216 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:138217 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:478218
8219 MockRead spdy_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068220 MockRead(SYNCHRONOUS, 0, 0) // Not async - return 0 immediately.
[email protected]26ef6582010-06-24 02:30:478221 };
8222
[email protected]a1595312012-01-22 03:25:048223 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]26ef6582010-06-24 02:30:478224 new DelayedSocketData(
8225 0, // don't wait in this case, immediate hangup.
8226 spdy_reads, arraysize(spdy_reads),
8227 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048228 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]26ef6582010-06-24 02:30:478229
[email protected]49639fa2011-12-20 23:22:418230 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:478231
8232 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8233 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8234
[email protected]49639fa2011-12-20 23:22:418235 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:478236 EXPECT_EQ(ERR_IO_PENDING, rv);
8237 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8238
[email protected]ecf96e52012-03-03 00:43:038239 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388240 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:478241}
[email protected]65d34382010-07-01 18:12:268242
[email protected]f45c1ee2010-08-03 00:54:308243TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8244 // This test ensures that the URL passed into the proxy is upgraded
8245 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:388246 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:038247 HttpStreamFactory::SetNextProtos(
[email protected]42baef7a2011-12-10 04:52:108248 MakeNextProtos(
8249 "http/1.1", "http1.1", "spdy/2.1", "spdy/2", "spdy", NULL));
[email protected]f45c1ee2010-08-03 00:54:308250
[email protected]81cdfcd2010-10-16 00:49:008251 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:308252 HttpAuthHandlerMock::Factory* auth_factory =
8253 new HttpAuthHandlerMock::Factory();
[email protected]767257802011-12-14 17:33:188254 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
8255 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:308256 auth_factory->set_do_init_from_challenge(true);
8257 session_deps.http_auth_handler_factory.reset(auth_factory);
8258
8259 HttpRequestInfo request;
8260 request.method = "GET";
8261 request.url = GURL("http://www.google.com");
8262 request.load_flags = 0;
8263
8264 // First round goes unauthenticated through the proxy.
8265 MockWrite data_writes_1[] = {
8266 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8267 "Host: www.google.com\r\n"
8268 "Proxy-Connection: keep-alive\r\n"
8269 "\r\n"),
8270 };
8271 MockRead data_reads_1[] = {
[email protected]8ddf8322012-02-23 18:08:068272 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:308273 MockRead("HTTP/1.1 200 OK\r\n"
[email protected]8d2f7012012-02-16 00:08:048274 "Alternate-Protocol: 443:npn-spdy/2.1\r\n"
[email protected]f45c1ee2010-08-03 00:54:308275 "Proxy-Connection: close\r\n"
8276 "\r\n"),
8277 };
8278 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8279 data_writes_1, arraysize(data_writes_1));
8280
8281 // Second round tries to tunnel to www.google.com due to the
8282 // Alternate-Protocol announcement in the first round. It fails due
8283 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:598284 // After the failure, a tunnel is established to www.google.com using
8285 // Proxy-Authorization headers. There is then a SPDY request round.
8286 //
[email protected]fe3b7dc2012-02-03 19:52:098287 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8288 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8289 // does a Disconnect and Connect on the same socket, rather than trying
8290 // to obtain a new one.
8291 //
[email protected]394816e92010-08-03 07:38:598292 // NOTE: Originally, the proxy response to the second CONNECT request
8293 // simply returned another 407 so the unit test could skip the SSL connection
8294 // establishment and SPDY framing issues. Alas, the
8295 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308296 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598297
[email protected]f45c1ee2010-08-03 00:54:308298 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8299 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8300 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8301
[email protected]394816e92010-08-03 07:38:598302 MockWrite data_writes_2[] = {
8303 // First connection attempt without Proxy-Authorization.
8304 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8305 "Host: www.google.com\r\n"
8306 "Proxy-Connection: keep-alive\r\n"
8307 "\r\n"),
8308
8309 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308310 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8311 "Host: www.google.com\r\n"
8312 "Proxy-Connection: keep-alive\r\n"
8313 "Proxy-Authorization: auth_token\r\n"
8314 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308315
[email protected]394816e92010-08-03 07:38:598316 // SPDY request
8317 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308318 };
[email protected]394816e92010-08-03 07:38:598319 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8320 "Proxy-Authenticate: Mock\r\n"
8321 "Proxy-Connection: close\r\n"
8322 "\r\n");
8323 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8324 MockRead data_reads_2[] = {
8325 // First connection attempt fails
[email protected]8ddf8322012-02-23 18:08:068326 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8327 MockRead(ASYNC, kRejectConnectResponse,
[email protected]394816e92010-08-03 07:38:598328 arraysize(kRejectConnectResponse) - 1, 1),
8329
8330 // Second connection attempt passes
[email protected]8ddf8322012-02-23 18:08:068331 MockRead(ASYNC, kAcceptConnectResponse,
[email protected]fe3b7dc2012-02-03 19:52:098332 arraysize(kAcceptConnectResponse) -1, 4),
[email protected]394816e92010-08-03 07:38:598333
8334 // SPDY response
[email protected]fe3b7dc2012-02-03 19:52:098335 CreateMockRead(*resp.get(), 6),
8336 CreateMockRead(*data.get(), 6),
[email protected]8ddf8322012-02-23 18:08:068337 MockRead(ASYNC, 0, 0, 6),
[email protected]394816e92010-08-03 07:38:598338 };
[email protected]a1595312012-01-22 03:25:048339 scoped_ptr<OrderedSocketData> data_2(
[email protected]394816e92010-08-03 07:38:598340 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8341 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308342
[email protected]8ddf8322012-02-23 18:08:068343 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]4c56dc02012-03-01 00:51:008344 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]f45c1ee2010-08-03 00:54:308345
[email protected]d973e99a2012-02-17 21:02:368346 MockConnect never_finishing_connect(SYNCHRONOUS, ERR_IO_PENDING);
[email protected]2d6728692011-03-12 01:39:558347 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8348 NULL, 0, NULL, 0);
8349 hanging_non_alternate_protocol_socket.set_connect_data(
8350 never_finishing_connect);
8351
[email protected]f45c1ee2010-08-03 00:54:308352 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598353 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308354 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558355 session_deps.socket_factory.AddSocketDataProvider(
8356 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308357 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8358
8359 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:418360 TestCompletionCallback callback_1;
[email protected]f45c1ee2010-08-03 00:54:308361 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418362 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308363 EXPECT_EQ(ERR_IO_PENDING, rv);
8364 EXPECT_EQ(OK, callback_1.WaitForResult());
8365
8366 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:418367 TestCompletionCallback callback_2;
[email protected]f45c1ee2010-08-03 00:54:308368 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418369 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308370 EXPECT_EQ(ERR_IO_PENDING, rv);
8371 EXPECT_EQ(OK, callback_2.WaitForResult());
8372 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508373 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:308374 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8375
8376 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:418377 TestCompletionCallback callback_3;
8378 rv = trans_2->RestartWithAuth(
8379 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:308380 EXPECT_EQ(ERR_IO_PENDING, rv);
8381 EXPECT_EQ(OK, callback_3.WaitForResult());
8382
8383 // After all that work, these two lines (or actually, just the scheme) are
8384 // what this test is all about. Make sure it happens correctly.
[email protected]767257802011-12-14 17:33:188385 const GURL& request_url = auth_handler->request_url();
[email protected]f45c1ee2010-08-03 00:54:308386 EXPECT_EQ("https", request_url.scheme());
8387 EXPECT_EQ("www.google.com", request_url.host());
8388
[email protected]ecf96e52012-03-03 00:43:038389 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388390 HttpStreamFactory::set_use_alternate_protocols(false);
8391}
8392
8393// Test that if we cancel the transaction as the connection is completing, that
8394// everything tears down correctly.
8395TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8396 // Setup everything about the connection to complete synchronously, so that
8397 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8398 // for is the callback from the HttpStreamRequest.
8399 // Then cancel the transaction.
8400 // Verify that we don't crash.
[email protected]d973e99a2012-02-17 21:02:368401 MockConnect mock_connect(SYNCHRONOUS, OK);
[email protected]8e6441ca2010-08-19 05:56:388402 MockRead data_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068403 MockRead(SYNCHRONOUS, "HTTP/1.0 200 OK\r\n\r\n"),
8404 MockRead(SYNCHRONOUS, "hello world"),
8405 MockRead(SYNCHRONOUS, OK),
[email protected]8e6441ca2010-08-19 05:56:388406 };
8407
[email protected]8e6441ca2010-08-19 05:56:388408 HttpRequestInfo request;
8409 request.method = "GET";
8410 request.url = GURL("http://www.google.com/");
8411 request.load_flags = 0;
8412
[email protected]cb9bf6ca2011-01-28 13:15:278413 SessionDependencies session_deps;
8414 session_deps.host_resolver->set_synchronous_mode(true);
8415 scoped_ptr<HttpTransaction> trans(
8416 new HttpNetworkTransaction(CreateSession(&session_deps)));
8417
[email protected]8e6441ca2010-08-19 05:56:388418 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8419 data.set_connect_data(mock_connect);
8420 session_deps.socket_factory.AddSocketDataProvider(&data);
8421
[email protected]49639fa2011-12-20 23:22:418422 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:388423
8424 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]49639fa2011-12-20 23:22:418425 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:388426 EXPECT_EQ(ERR_IO_PENDING, rv);
8427 trans.reset(); // Cancel the transaction here.
8428
8429 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308430}
8431
[email protected]76a505b2010-08-25 06:23:008432// Test a basic GET request through a proxy.
8433TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008434 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008435 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8436 session_deps.net_log = log.bound().net_log();
8437 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8438
[email protected]76a505b2010-08-25 06:23:008439 HttpRequestInfo request;
8440 request.method = "GET";
8441 request.url = GURL("http://www.google.com/");
8442
8443 MockWrite data_writes1[] = {
8444 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8445 "Host: www.google.com\r\n"
8446 "Proxy-Connection: keep-alive\r\n\r\n"),
8447 };
8448
8449 MockRead data_reads1[] = {
8450 MockRead("HTTP/1.1 200 OK\r\n"),
8451 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8452 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068453 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008454 };
8455
8456 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8457 data_writes1, arraysize(data_writes1));
8458 session_deps.socket_factory.AddSocketDataProvider(&data1);
8459
[email protected]49639fa2011-12-20 23:22:418460 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008461
[email protected]0b0bf032010-09-21 18:08:508462 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8463
[email protected]49639fa2011-12-20 23:22:418464 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008465 EXPECT_EQ(ERR_IO_PENDING, rv);
8466
8467 rv = callback1.WaitForResult();
8468 EXPECT_EQ(OK, rv);
8469
8470 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508471 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008472
8473 EXPECT_TRUE(response->headers->IsKeepAlive());
8474 EXPECT_EQ(200, response->headers->response_code());
8475 EXPECT_EQ(100, response->headers->GetContentLength());
8476 EXPECT_TRUE(response->was_fetched_via_proxy);
8477 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8478}
8479
8480// Test a basic HTTPS GET request through a proxy.
8481TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008482 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008483 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8484 session_deps.net_log = log.bound().net_log();
8485 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8486
[email protected]76a505b2010-08-25 06:23:008487 HttpRequestInfo request;
8488 request.method = "GET";
8489 request.url = GURL("https://www.google.com/");
8490
8491 // Since we have proxy, should try to establish tunnel.
8492 MockWrite data_writes1[] = {
8493 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8494 "Host: www.google.com\r\n"
8495 "Proxy-Connection: keep-alive\r\n\r\n"),
8496
8497 MockWrite("GET / HTTP/1.1\r\n"
8498 "Host: www.google.com\r\n"
8499 "Connection: keep-alive\r\n\r\n"),
8500 };
8501
8502 MockRead data_reads1[] = {
8503 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8504
8505 MockRead("HTTP/1.1 200 OK\r\n"),
8506 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8507 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068508 MockRead(SYNCHRONOUS, OK),
[email protected]76a505b2010-08-25 06:23:008509 };
8510
8511 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8512 data_writes1, arraysize(data_writes1));
8513 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:068514 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]76a505b2010-08-25 06:23:008515 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8516
[email protected]49639fa2011-12-20 23:22:418517 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008518
[email protected]0b0bf032010-09-21 18:08:508519 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8520
[email protected]49639fa2011-12-20 23:22:418521 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008522 EXPECT_EQ(ERR_IO_PENDING, rv);
8523
8524 rv = callback1.WaitForResult();
8525 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408526 net::CapturingNetLog::EntryList entries;
8527 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008528 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408529 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008530 NetLog::PHASE_NONE);
8531 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408532 entries, pos,
[email protected]76a505b2010-08-25 06:23:008533 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8534 NetLog::PHASE_NONE);
8535
8536 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508537 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008538
8539 EXPECT_TRUE(response->headers->IsKeepAlive());
8540 EXPECT_EQ(200, response->headers->response_code());
8541 EXPECT_EQ(100, response->headers->GetContentLength());
8542 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8543 EXPECT_TRUE(response->was_fetched_via_proxy);
8544}
8545
8546// Test a basic HTTPS GET request through a proxy, but the server hangs up
8547// while establishing the tunnel.
8548TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008549 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008550 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8551 session_deps.net_log = log.bound().net_log();
8552 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8553
[email protected]76a505b2010-08-25 06:23:008554 HttpRequestInfo request;
8555 request.method = "GET";
8556 request.url = GURL("https://www.google.com/");
8557
8558 // Since we have proxy, should try to establish tunnel.
8559 MockWrite data_writes1[] = {
8560 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8561 "Host: www.google.com\r\n"
8562 "Proxy-Connection: keep-alive\r\n\r\n"),
8563
8564 MockWrite("GET / HTTP/1.1\r\n"
8565 "Host: www.google.com\r\n"
8566 "Connection: keep-alive\r\n\r\n"),
8567 };
8568
8569 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:068570 MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]76a505b2010-08-25 06:23:008571 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
[email protected]8ddf8322012-02-23 18:08:068572 MockRead(ASYNC, 0, 0), // EOF
[email protected]76a505b2010-08-25 06:23:008573 };
8574
8575 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8576 data_writes1, arraysize(data_writes1));
8577 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]8ddf8322012-02-23 18:08:068578 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]76a505b2010-08-25 06:23:008579 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8580
[email protected]49639fa2011-12-20 23:22:418581 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008582
[email protected]0b0bf032010-09-21 18:08:508583 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8584
[email protected]49639fa2011-12-20 23:22:418585 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008586 EXPECT_EQ(ERR_IO_PENDING, rv);
8587
8588 rv = callback1.WaitForResult();
8589 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408590 net::CapturingNetLog::EntryList entries;
8591 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008592 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408593 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008594 NetLog::PHASE_NONE);
8595 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408596 entries, pos,
[email protected]76a505b2010-08-25 06:23:008597 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8598 NetLog::PHASE_NONE);
8599}
8600
[email protected]749eefa82010-09-13 22:14:038601// Test for crbug.com/55424.
8602TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8603 SessionDependencies session_deps;
8604
8605 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8606 "https://www.google.com", false, 1, LOWEST));
8607 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8608
8609 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8610 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8611 MockRead spdy_reads[] = {
8612 CreateMockRead(*resp),
8613 CreateMockRead(*data),
[email protected]8ddf8322012-02-23 18:08:068614 MockRead(ASYNC, 0, 0),
[email protected]749eefa82010-09-13 22:14:038615 };
8616
[email protected]a1595312012-01-22 03:25:048617 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]749eefa82010-09-13 22:14:038618 new DelayedSocketData(
8619 1, // wait for one write to finish before reading.
8620 spdy_reads, arraysize(spdy_reads),
8621 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048622 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]749eefa82010-09-13 22:14:038623
[email protected]8ddf8322012-02-23 18:08:068624 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]4c56dc02012-03-01 00:51:008625 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]749eefa82010-09-13 22:14:038626 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8627
8628 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8629
8630 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388631 HostPortPair host_port_pair("www.google.com", 443);
8632 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038633 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318634 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288635 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:298636 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]6ecf2b92011-12-15 01:14:528637 TestCompletionCallback callback;
[email protected]02b0c342010-09-25 21:09:388638
8639 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8640 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288641 connection->Init(host_port_pair.ToString(), transport_params,
[email protected]6ecf2b92011-12-15 01:14:528642 LOWEST, callback.callback(),
[email protected]a42dbd142011-11-17 16:42:028643 session->GetTransportSocketPool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388644 EXPECT_EQ(OK, callback.WaitForResult());
8645 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038646
8647 HttpRequestInfo request;
8648 request.method = "GET";
8649 request.url = GURL("https://www.google.com/");
8650 request.load_flags = 0;
8651
8652 // This is the important line that marks this as a preconnect.
8653 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8654
8655 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8656
[email protected]49639fa2011-12-20 23:22:418657 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:038658 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:418659 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:038660}
8661
[email protected]73b8dd222010-11-11 19:55:248662// Given a net error, cause that error to be returned from the first Write()
8663// call and verify that the HttpTransaction fails with that error.
[email protected]8ddf8322012-02-23 18:08:068664static void CheckErrorIsPassedBack(int error, IoMode mode) {
[email protected]cb9bf6ca2011-01-28 13:15:278665 net::HttpRequestInfo request_info;
8666 request_info.url = GURL("https://www.example.com/");
8667 request_info.method = "GET";
8668 request_info.load_flags = net::LOAD_NORMAL;
8669
[email protected]73b8dd222010-11-11 19:55:248670 SessionDependencies session_deps;
8671
[email protected]8ddf8322012-02-23 18:08:068672 SSLSocketDataProvider ssl_data(mode, OK);
[email protected]73b8dd222010-11-11 19:55:248673 net::MockWrite data_writes[] = {
[email protected]8ddf8322012-02-23 18:08:068674 net::MockWrite(mode, error),
[email protected]73b8dd222010-11-11 19:55:248675 };
8676 net::StaticSocketDataProvider data(NULL, 0,
8677 data_writes, arraysize(data_writes));
8678 session_deps.socket_factory.AddSocketDataProvider(&data);
8679 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8680
8681 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8682 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8683
[email protected]49639fa2011-12-20 23:22:418684 TestCompletionCallback callback;
8685 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]73b8dd222010-11-11 19:55:248686 if (rv == net::ERR_IO_PENDING)
8687 rv = callback.WaitForResult();
8688 ASSERT_EQ(error, rv);
8689}
8690
8691TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8692 // Just check a grab bag of cert errors.
8693 static const int kErrors[] = {
8694 ERR_CERT_COMMON_NAME_INVALID,
8695 ERR_CERT_AUTHORITY_INVALID,
8696 ERR_CERT_DATE_INVALID,
8697 };
8698 for (size_t i = 0; i < arraysize(kErrors); i++) {
[email protected]8ddf8322012-02-23 18:08:068699 CheckErrorIsPassedBack(kErrors[i], ASYNC);
8700 CheckErrorIsPassedBack(kErrors[i], SYNCHRONOUS);
[email protected]73b8dd222010-11-11 19:55:248701 }
8702}
8703
[email protected]bd0b6772011-01-11 19:59:308704// Ensure that a client certificate is removed from the SSL client auth
8705// cache when:
8706// 1) No proxy is involved.
8707// 2) TLS False Start is disabled.
8708// 3) The initial TLS handshake requests a client certificate.
8709// 4) The client supplies an invalid/unacceptable certificate.
8710TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278711 net::HttpRequestInfo request_info;
8712 request_info.url = GURL("https://www.example.com/");
8713 request_info.method = "GET";
8714 request_info.load_flags = net::LOAD_NORMAL;
8715
[email protected]bd0b6772011-01-11 19:59:308716 SessionDependencies session_deps;
8717
8718 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8719 cert_request->host_and_port = "www.example.com:443";
8720
8721 // [ssl_]data1 contains the data for the first SSL handshake. When a
8722 // CertificateRequest is received for the first time, the handshake will
8723 // be aborted to allow the caller to provide a certificate.
[email protected]8ddf8322012-02-23 18:08:068724 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:308725 ssl_data1.cert_request_info = cert_request.get();
8726 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8727 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8728 session_deps.socket_factory.AddSocketDataProvider(&data1);
8729
8730 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8731 // False Start is not being used, the result of the SSL handshake will be
8732 // returned as part of the SSLClientSocket::Connect() call. This test
8733 // matches the result of a server sending a handshake_failure alert,
8734 // rather than a Finished message, because it requires a client
8735 // certificate and none was supplied.
[email protected]8ddf8322012-02-23 18:08:068736 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:308737 ssl_data2.cert_request_info = cert_request.get();
8738 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8739 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8740 session_deps.socket_factory.AddSocketDataProvider(&data2);
8741
8742 // [ssl_]data3 contains the data for the third SSL handshake. When a
8743 // connection to a server fails during an SSL handshake,
8744 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8745 // connection was attempted with TLSv1. This is transparent to the caller
8746 // of the HttpNetworkTransaction. Because this test failure is due to
8747 // requiring a client certificate, this fallback handshake should also
8748 // fail.
[email protected]8ddf8322012-02-23 18:08:068749 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
[email protected]bd0b6772011-01-11 19:59:308750 ssl_data3.cert_request_info = cert_request.get();
8751 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8752 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8753 session_deps.socket_factory.AddSocketDataProvider(&data3);
8754
8755 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8756 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8757
[email protected]bd0b6772011-01-11 19:59:308758 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:418759 TestCompletionCallback callback;
8760 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308761 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8762
8763 // Complete the SSL handshake, which should abort due to requiring a
8764 // client certificate.
8765 rv = callback.WaitForResult();
8766 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8767
8768 // Indicate that no certificate should be supplied. From the perspective
8769 // of SSLClientCertCache, NULL is just as meaningful as a real
8770 // certificate, so this is the same as supply a
8771 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418772 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308773 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8774
8775 // Ensure the certificate was added to the client auth cache before
8776 // allowing the connection to continue restarting.
8777 scoped_refptr<X509Certificate> client_cert;
8778 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8779 &client_cert));
8780 ASSERT_EQ(NULL, client_cert.get());
8781
8782 // Restart the handshake. This will consume ssl_data2, which fails, and
8783 // then consume ssl_data3, which should also fail. The result code is
8784 // checked against what ssl_data3 should return.
8785 rv = callback.WaitForResult();
8786 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8787
8788 // Ensure that the client certificate is removed from the cache on a
8789 // handshake failure.
8790 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8791 &client_cert));
8792}
8793
8794// Ensure that a client certificate is removed from the SSL client auth
8795// cache when:
8796// 1) No proxy is involved.
8797// 2) TLS False Start is enabled.
8798// 3) The initial TLS handshake requests a client certificate.
8799// 4) The client supplies an invalid/unacceptable certificate.
8800TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278801 net::HttpRequestInfo request_info;
8802 request_info.url = GURL("https://www.example.com/");
8803 request_info.method = "GET";
8804 request_info.load_flags = net::LOAD_NORMAL;
8805
[email protected]bd0b6772011-01-11 19:59:308806 SessionDependencies session_deps;
8807
8808 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8809 cert_request->host_and_port = "www.example.com:443";
8810
8811 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8812 // return successfully after reading up to the peer's Certificate message.
8813 // This is to allow the caller to call SSLClientSocket::Write(), which can
8814 // enqueue application data to be sent in the same packet as the
8815 // ChangeCipherSpec and Finished messages.
8816 // The actual handshake will be finished when SSLClientSocket::Read() is
8817 // called, which expects to process the peer's ChangeCipherSpec and
8818 // Finished messages. If there was an error negotiating with the peer,
8819 // such as due to the peer requiring a client certificate when none was
8820 // supplied, the alert sent by the peer won't be processed until Read() is
8821 // called.
8822
8823 // Like the non-False Start case, when a client certificate is requested by
8824 // the peer, the handshake is aborted during the Connect() call.
8825 // [ssl_]data1 represents the initial SSL handshake with the peer.
[email protected]8ddf8322012-02-23 18:08:068826 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]bd0b6772011-01-11 19:59:308827 ssl_data1.cert_request_info = cert_request.get();
8828 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8829 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8830 session_deps.socket_factory.AddSocketDataProvider(&data1);
8831
8832 // When a client certificate is supplied, Connect() will not be aborted
8833 // when the peer requests the certificate. Instead, the handshake will
8834 // artificially succeed, allowing the caller to write the HTTP request to
8835 // the socket. The handshake messages are not processed until Read() is
8836 // called, which then detects that the handshake was aborted, due to the
8837 // peer sending a handshake_failure because it requires a client
8838 // certificate.
[email protected]8ddf8322012-02-23 18:08:068839 SSLSocketDataProvider ssl_data2(ASYNC, net::OK);
[email protected]bd0b6772011-01-11 19:59:308840 ssl_data2.cert_request_info = cert_request.get();
8841 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8842 net::MockRead data2_reads[] = {
[email protected]8ddf8322012-02-23 18:08:068843 net::MockRead(ASYNC /* async */, net::ERR_SSL_PROTOCOL_ERROR),
[email protected]bd0b6772011-01-11 19:59:308844 };
8845 net::StaticSocketDataProvider data2(
8846 data2_reads, arraysize(data2_reads), NULL, 0);
8847 session_deps.socket_factory.AddSocketDataProvider(&data2);
8848
8849 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8850 // the data for the SSL handshake once the TLSv1 connection falls back to
8851 // SSLv3. It has the same behaviour as [ssl_]data2.
[email protected]8ddf8322012-02-23 18:08:068852 SSLSocketDataProvider ssl_data3(ASYNC, net::OK);
[email protected]bd0b6772011-01-11 19:59:308853 ssl_data3.cert_request_info = cert_request.get();
8854 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8855 net::StaticSocketDataProvider data3(
8856 data2_reads, arraysize(data2_reads), NULL, 0);
8857 session_deps.socket_factory.AddSocketDataProvider(&data3);
8858
8859 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8860 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8861
[email protected]bd0b6772011-01-11 19:59:308862 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:418863 TestCompletionCallback callback;
8864 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308865 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8866
8867 // Complete the SSL handshake, which should abort due to requiring a
8868 // client certificate.
8869 rv = callback.WaitForResult();
8870 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8871
8872 // Indicate that no certificate should be supplied. From the perspective
8873 // of SSLClientCertCache, NULL is just as meaningful as a real
8874 // certificate, so this is the same as supply a
8875 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418876 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308877 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8878
8879 // Ensure the certificate was added to the client auth cache before
8880 // allowing the connection to continue restarting.
8881 scoped_refptr<X509Certificate> client_cert;
8882 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8883 &client_cert));
8884 ASSERT_EQ(NULL, client_cert.get());
8885
8886
8887 // Restart the handshake. This will consume ssl_data2, which fails, and
8888 // then consume ssl_data3, which should also fail. The result code is
8889 // checked against what ssl_data3 should return.
8890 rv = callback.WaitForResult();
8891 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8892
8893 // Ensure that the client certificate is removed from the cache on a
8894 // handshake failure.
8895 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8896 &client_cert));
8897}
8898
[email protected]8c405132011-01-11 22:03:188899// Ensure that a client certificate is removed from the SSL client auth
8900// cache when:
8901// 1) An HTTPS proxy is involved.
8902// 3) The HTTPS proxy requests a client certificate.
8903// 4) The client supplies an invalid/unacceptable certificate for the
8904// proxy.
8905// The test is repeated twice, first for connecting to an HTTPS endpoint,
8906// then for connecting to an HTTP endpoint.
8907TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8908 SessionDependencies session_deps(
8909 ProxyService::CreateFixed("https://proxy:70"));
8910 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8911 session_deps.net_log = log.bound().net_log();
8912
8913 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8914 cert_request->host_and_port = "proxy:70";
8915
8916 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8917 // [ssl_]data[1-3]. Rather than represending the endpoint
8918 // (www.example.com:443), they represent failures with the HTTPS proxy
8919 // (proxy:70).
[email protected]8ddf8322012-02-23 18:08:068920 SSLSocketDataProvider ssl_data1(ASYNC, net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
[email protected]8c405132011-01-11 22:03:188921 ssl_data1.cert_request_info = cert_request.get();
8922 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8923 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8924 session_deps.socket_factory.AddSocketDataProvider(&data1);
8925
[email protected]8ddf8322012-02-23 18:08:068926 SSLSocketDataProvider ssl_data2(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:188927 ssl_data2.cert_request_info = cert_request.get();
8928 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8929 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8930 session_deps.socket_factory.AddSocketDataProvider(&data2);
8931
[email protected]8ddf8322012-02-23 18:08:068932 SSLSocketDataProvider ssl_data3(ASYNC, net::ERR_SSL_PROTOCOL_ERROR);
[email protected]8c405132011-01-11 22:03:188933 ssl_data3.cert_request_info = cert_request.get();
8934 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8935 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8936 session_deps.socket_factory.AddSocketDataProvider(&data3);
8937
8938 net::HttpRequestInfo requests[2];
8939 requests[0].url = GURL("https://www.example.com/");
8940 requests[0].method = "GET";
8941 requests[0].load_flags = net::LOAD_NORMAL;
8942
8943 requests[1].url = GURL("http://www.example.com/");
8944 requests[1].method = "GET";
8945 requests[1].load_flags = net::LOAD_NORMAL;
8946
8947 for (size_t i = 0; i < arraysize(requests); ++i) {
8948 session_deps.socket_factory.ResetNextMockIndexes();
8949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8950 scoped_ptr<HttpNetworkTransaction> trans(
8951 new HttpNetworkTransaction(session));
8952
8953 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:418954 TestCompletionCallback callback;
8955 int rv = trans->Start(
8956 &requests[i], callback.callback(), net::BoundNetLog());
[email protected]8c405132011-01-11 22:03:188957 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8958
8959 // Complete the SSL handshake, which should abort due to requiring a
8960 // client certificate.
8961 rv = callback.WaitForResult();
8962 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8963
8964 // Indicate that no certificate should be supplied. From the perspective
8965 // of SSLClientCertCache, NULL is just as meaningful as a real
8966 // certificate, so this is the same as supply a
8967 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418968 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]8c405132011-01-11 22:03:188969 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8970
8971 // Ensure the certificate was added to the client auth cache before
8972 // allowing the connection to continue restarting.
8973 scoped_refptr<X509Certificate> client_cert;
8974 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8975 &client_cert));
8976 ASSERT_EQ(NULL, client_cert.get());
8977 // Ensure the certificate was NOT cached for the endpoint. This only
8978 // applies to HTTPS requests, but is fine to check for HTTP requests.
8979 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8980 &client_cert));
8981
8982 // Restart the handshake. This will consume ssl_data2, which fails, and
8983 // then consume ssl_data3, which should also fail. The result code is
8984 // checked against what ssl_data3 should return.
8985 rv = callback.WaitForResult();
8986 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8987
8988 // Now that the new handshake has failed, ensure that the client
8989 // certificate was removed from the client auth cache.
8990 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8991 &client_cert));
8992 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8993 &client_cert));
8994 }
8995}
8996
[email protected]5c288bc2011-07-26 15:12:058997void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8998 SpdySessionPoolPeer* pool_peer,
8999 std::string host,
9000 int port,
9001 std::string iplist) {
9002 // Create a host resolver dependency that returns address |iplist| for
9003 // resolutions of |host|.
9004 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:049005
[email protected]5c288bc2011-07-26 15:12:059006 // Setup a HostPortProxyPair.
9007 HostPortPair host_port_pair(host, port);
9008 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
9009 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:049010
[email protected]5c288bc2011-07-26 15:12:059011 // Resolve the host and port.
9012 AddressList addresses;
9013 HostResolver::RequestInfo info(host_port_pair);
[email protected]aa22b242011-11-16 18:58:299014 TestCompletionCallback callback;
9015 int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479016 BoundNetLog());
9017 if (rv == ERR_IO_PENDING)
9018 rv = callback.WaitForResult();
9019 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:049020
[email protected]5c288bc2011-07-26 15:12:059021 // Add the first address as an alias. It would have been better to call
9022 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
9023 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
9024 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
9025 // the |pair|.
9026 const addrinfo* address = addresses.head();
9027 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:049028}
9029
[email protected]e3ceb682011-06-28 23:55:469030TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
9031 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:039032 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469033
9034 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
9035 SessionDependencies session_deps;
9036 MockCachingHostResolver host_resolver;
9037 net::HttpNetworkSession::Params params;
9038 params.client_socket_factory = &session_deps.socket_factory;
9039 params.host_resolver = &host_resolver;
9040 params.cert_verifier = session_deps.cert_verifier.get();
9041 params.proxy_service = session_deps.proxy_service.get();
9042 params.ssl_config_service = session_deps.ssl_config_service;
9043 params.http_auth_handler_factory =
9044 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539045 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469046 params.net_log = session_deps.net_log;
9047 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269048 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9049 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469050
[email protected]8ddf8322012-02-23 18:08:069051 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]4c56dc02012-03-01 00:51:009052 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]e3ceb682011-06-28 23:55:469053 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9054
9055 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9056 "https://www.google.com", false, 1, LOWEST));
9057 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9058 "https://www.gmail.com", false, 3, LOWEST));
9059 MockWrite spdy_writes[] = {
9060 CreateMockWrite(*host1_req, 1),
9061 CreateMockWrite(*host2_req, 4),
9062 };
9063 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9064 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9065 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9066 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9067 MockRead spdy_reads[] = {
9068 CreateMockRead(*host1_resp, 2),
9069 CreateMockRead(*host1_resp_body, 3),
9070 CreateMockRead(*host2_resp, 5),
9071 CreateMockRead(*host2_resp_body, 6),
[email protected]8ddf8322012-02-23 18:08:069072 MockRead(ASYNC, 0, 7),
[email protected]e3ceb682011-06-28 23:55:469073 };
9074
[email protected]a1595312012-01-22 03:25:049075 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:469076 new OrderedSocketData(
9077 spdy_reads, arraysize(spdy_reads),
9078 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:049079 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:469080
[email protected]aa22b242011-11-16 18:58:299081 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469082 HttpRequestInfo request1;
9083 request1.method = "GET";
9084 request1.url = GURL("https://www.google.com/");
9085 request1.load_flags = 0;
9086 HttpNetworkTransaction trans1(session);
9087
[email protected]49639fa2011-12-20 23:22:419088 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469089 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419090 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469091
9092 const HttpResponseInfo* response = trans1.GetResponseInfo();
9093 ASSERT_TRUE(response != NULL);
9094 ASSERT_TRUE(response->headers != NULL);
9095 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9096
9097 std::string response_data;
9098 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9099 EXPECT_EQ("hello!", response_data);
9100
9101 // Preload www.gmail.com into HostCache.
9102 HostPortPair host_port("www.gmail.com", 443);
9103 HostResolver::RequestInfo resolve_info(host_port);
9104 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299105 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479106 BoundNetLog());
9107 EXPECT_EQ(ERR_IO_PENDING, rv);
9108 rv = callback.WaitForResult();
9109 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469110
[email protected]5c288bc2011-07-26 15:12:059111 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9112 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9113 // (www.google.com, 443).
9114 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
9115 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049116
[email protected]e3ceb682011-06-28 23:55:469117 HttpRequestInfo request2;
9118 request2.method = "GET";
9119 request2.url = GURL("https://www.gmail.com/");
9120 request2.load_flags = 0;
9121 HttpNetworkTransaction trans2(session);
9122
[email protected]49639fa2011-12-20 23:22:419123 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469124 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419125 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469126
9127 response = trans2.GetResponseInfo();
9128 ASSERT_TRUE(response != NULL);
9129 ASSERT_TRUE(response->headers != NULL);
9130 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9131 EXPECT_TRUE(response->was_fetched_via_spdy);
9132 EXPECT_TRUE(response->was_npn_negotiated);
9133 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9134 EXPECT_EQ("hello!", response_data);
9135
[email protected]ecf96e52012-03-03 00:43:039136 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469137 HttpStreamFactory::set_use_alternate_protocols(false);
9138}
9139
9140class OneTimeCachingHostResolver : public net::HostResolver {
9141 public:
9142 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9143 : host_port_(host_port) {}
9144 virtual ~OneTimeCachingHostResolver() {}
9145
9146 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9147
9148 // HostResolver methods:
9149 virtual int Resolve(const RequestInfo& info,
9150 AddressList* addresses,
[email protected]aa22b242011-11-16 18:58:299151 const CompletionCallback& callback,
[email protected]e3ceb682011-06-28 23:55:469152 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:409153 const BoundNetLog& net_log) OVERRIDE {
9154 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:469155 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:409156 }
9157
9158 virtual int ResolveFromCache(const RequestInfo& info,
9159 AddressList* addresses,
9160 const BoundNetLog& net_log) OVERRIDE {
9161 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9162 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:099163 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:469164 return rv;
9165 }
9166
[email protected]95a214c2011-08-04 21:50:409167 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469168 host_resolver_.CancelRequest(req);
9169 }
9170
[email protected]46da33be2011-07-19 21:58:049171 MockCachingHostResolver* GetMockHostResolver() {
9172 return &host_resolver_;
9173 }
9174
[email protected]e3ceb682011-06-28 23:55:469175 private:
9176 MockCachingHostResolver host_resolver_;
9177 const HostPortPair host_port_;
9178};
9179
9180TEST_F(HttpNetworkTransactionTest,
9181 UseIPConnectionPoolingWithHostCacheExpiration) {
9182 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]ecf96e52012-03-03 00:43:039183 HttpStreamFactory::SetNextProtos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469184
9185 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9186 SessionDependencies session_deps;
9187 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9188 net::HttpNetworkSession::Params params;
9189 params.client_socket_factory = &session_deps.socket_factory;
9190 params.host_resolver = &host_resolver;
9191 params.cert_verifier = session_deps.cert_verifier.get();
9192 params.proxy_service = session_deps.proxy_service.get();
9193 params.ssl_config_service = session_deps.ssl_config_service;
9194 params.http_auth_handler_factory =
9195 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539196 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469197 params.net_log = session_deps.net_log;
9198 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269199 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9200 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469201
[email protected]8ddf8322012-02-23 18:08:069202 SSLSocketDataProvider ssl(ASYNC, OK);
[email protected]4c56dc02012-03-01 00:51:009203 ssl.SetNextProto(SSLClientSocket::kProtoSPDY21);
[email protected]e3ceb682011-06-28 23:55:469204 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9205
9206 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9207 "https://www.google.com", false, 1, LOWEST));
9208 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9209 "https://www.gmail.com", false, 3, LOWEST));
9210 MockWrite spdy_writes[] = {
9211 CreateMockWrite(*host1_req, 1),
9212 CreateMockWrite(*host2_req, 4),
9213 };
9214 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9215 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9216 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9217 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9218 MockRead spdy_reads[] = {
9219 CreateMockRead(*host1_resp, 2),
9220 CreateMockRead(*host1_resp_body, 3),
9221 CreateMockRead(*host2_resp, 5),
9222 CreateMockRead(*host2_resp_body, 6),
[email protected]8ddf8322012-02-23 18:08:069223 MockRead(ASYNC, 0, 7),
[email protected]e3ceb682011-06-28 23:55:469224 };
9225
[email protected]a1595312012-01-22 03:25:049226 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:469227 new OrderedSocketData(
9228 spdy_reads, arraysize(spdy_reads),
9229 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:049230 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:469231
[email protected]aa22b242011-11-16 18:58:299232 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469233 HttpRequestInfo request1;
9234 request1.method = "GET";
9235 request1.url = GURL("https://www.google.com/");
9236 request1.load_flags = 0;
9237 HttpNetworkTransaction trans1(session);
9238
[email protected]49639fa2011-12-20 23:22:419239 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469240 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419241 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469242
9243 const HttpResponseInfo* response = trans1.GetResponseInfo();
9244 ASSERT_TRUE(response != NULL);
9245 ASSERT_TRUE(response->headers != NULL);
9246 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9247
9248 std::string response_data;
9249 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9250 EXPECT_EQ("hello!", response_data);
9251
9252 // Preload cache entries into HostCache.
9253 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9254 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299255 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479256 BoundNetLog());
9257 EXPECT_EQ(ERR_IO_PENDING, rv);
9258 rv = callback.WaitForResult();
9259 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469260
9261 HttpRequestInfo request2;
9262 request2.method = "GET";
9263 request2.url = GURL("https://www.gmail.com/");
9264 request2.load_flags = 0;
9265 HttpNetworkTransaction trans2(session);
9266
[email protected]5c288bc2011-07-26 15:12:059267 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9268 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9269 // (www.google.com, 443).
9270 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9271 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049272
[email protected]49639fa2011-12-20 23:22:419273 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469274 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419275 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469276
9277 response = trans2.GetResponseInfo();
9278 ASSERT_TRUE(response != NULL);
9279 ASSERT_TRUE(response->headers != NULL);
9280 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9281 EXPECT_TRUE(response->was_fetched_via_spdy);
9282 EXPECT_TRUE(response->was_npn_negotiated);
9283 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9284 EXPECT_EQ("hello!", response_data);
9285
[email protected]ecf96e52012-03-03 00:43:039286 HttpStreamFactory::SetNextProtos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469287 HttpStreamFactory::set_use_alternate_protocols(false);
9288}
9289
[email protected]5a60c8b2011-10-19 20:14:299290TEST_F(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
9291 MockRead data_reads1[] = {
[email protected]8ddf8322012-02-23 18:08:069292 MockRead(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
[email protected]5a60c8b2011-10-19 20:14:299293 };
9294 MockRead data_reads2[] = {
9295 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9296 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069297 MockRead(SYNCHRONOUS, OK),
[email protected]5a60c8b2011-10-19 20:14:299298 };
9299 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
9300 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
9301 StaticSocketDataProvider* data[] = { &data1, &data2 };
9302
9303 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9304
9305 EXPECT_EQ(OK, out.rv);
9306 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9307 EXPECT_EQ("hello world", out.response_data);
9308}
9309
9310TEST_F(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
9311 MockWrite data_writes1[] = {
[email protected]8ddf8322012-02-23 18:08:069312 MockWrite(SYNCHRONOUS, ERR_PIPELINE_EVICTION),
[email protected]5a60c8b2011-10-19 20:14:299313 };
9314 MockWrite data_writes2[] = {
9315 MockWrite("GET / HTTP/1.1\r\n"
9316 "Host: www.google.com\r\n"
9317 "Connection: keep-alive\r\n\r\n"),
9318 };
9319 MockRead data_reads2[] = {
9320 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9321 MockRead("hello world"),
[email protected]8ddf8322012-02-23 18:08:069322 MockRead(SYNCHRONOUS, OK),
[email protected]5a60c8b2011-10-19 20:14:299323 };
9324 StaticSocketDataProvider data1(NULL, 0,
9325 data_writes1, arraysize(data_writes1));
9326 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9327 data_writes2, arraysize(data_writes2));
9328 StaticSocketDataProvider* data[] = { &data1, &data2 };
9329
9330 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9331
9332 EXPECT_EQ(OK, out.rv);
9333 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9334 EXPECT_EQ("hello world", out.response_data);
9335}
9336
[email protected]89ceba9a2009-03-21 03:46:069337} // namespace net