blob: 75b6a988d465d11d2ad90549c0d3fae9e9fb0210 [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]1ad77dc2012-01-27 03:51:20380 "Alternate-Protocol: 443:npn-spdy/2.1\r\n\r\n";
[email protected]dae22c52010-07-30 02:16:35381
[email protected]79cb5c12011-09-12 13:12:04382// Helper functions for validating that AuthChallengeInfo's are correctly
383// configured for common cases.
384bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
385 if (!auth_challenge)
386 return false;
387 EXPECT_FALSE(auth_challenge->is_proxy);
388 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
389 EXPECT_EQ("MyRealm1", auth_challenge->realm);
390 EXPECT_EQ("basic", auth_challenge->scheme);
391 return true;
392}
393
394bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
395 if (!auth_challenge)
396 return false;
397 EXPECT_TRUE(auth_challenge->is_proxy);
398 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
399 EXPECT_EQ("MyRealm1", auth_challenge->realm);
400 EXPECT_EQ("basic", auth_challenge->scheme);
401 return true;
402}
403
404bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
405 if (!auth_challenge)
406 return false;
407 EXPECT_FALSE(auth_challenge->is_proxy);
408 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
409 EXPECT_EQ("digestive", auth_challenge->realm);
410 EXPECT_EQ("digest", auth_challenge->scheme);
411 return true;
412}
413
414bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
415 if (!auth_challenge)
416 return false;
417 EXPECT_FALSE(auth_challenge->is_proxy);
418 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
419 EXPECT_EQ(std::string(), auth_challenge->realm);
420 EXPECT_EQ("ntlm", auth_challenge->scheme);
421 return true;
422}
423
[email protected]231d5a32008-09-13 00:45:27424TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59425 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40426 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43427 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27428}
429
430TEST_F(HttpNetworkTransactionTest, SimpleGET) {
431 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35432 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
433 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42434 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27435 };
[email protected]31a2bfe2010-02-09 08:03:39436 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
437 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42438 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27439 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
440 EXPECT_EQ("hello world", out.response_data);
441}
442
443// Response with no status line.
444TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
445 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35446 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42447 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27448 };
[email protected]31a2bfe2010-02-09 08:03:39449 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
450 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42451 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27452 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
453 EXPECT_EQ("hello world", out.response_data);
454}
455
456// Allow up to 4 bytes of junk to precede status line.
457TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
458 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35459 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42460 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27461 };
[email protected]31a2bfe2010-02-09 08:03:39462 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
463 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42464 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27465 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
466 EXPECT_EQ("DATA", out.response_data);
467}
468
469// Allow up to 4 bytes of junk to precede status line.
470TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
471 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35472 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42473 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27474 };
[email protected]31a2bfe2010-02-09 08:03:39475 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
476 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42477 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27478 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
479 EXPECT_EQ("DATA", out.response_data);
480}
481
482// Beyond 4 bytes of slop and it should fail to find a status line.
483TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
484 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35485 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42486 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27487 };
[email protected]31a2bfe2010-02-09 08:03:39488 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
489 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42490 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25491 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
492 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27493}
494
495// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
496TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
497 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35498 MockRead("\n"),
499 MockRead("\n"),
500 MockRead("Q"),
501 MockRead("J"),
502 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42503 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27504 };
[email protected]31a2bfe2010-02-09 08:03:39505 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
506 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42507 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27508 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
509 EXPECT_EQ("DATA", out.response_data);
510}
511
512// Close the connection before enough bytes to have a status line.
513TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
514 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35515 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42516 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27517 };
[email protected]31a2bfe2010-02-09 08:03:39518 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
519 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42520 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27521 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
522 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52523}
524
[email protected]f9d44aa2008-09-23 23:57:17525// Simulate a 204 response, lacking a Content-Length header, sent over a
526// persistent connection. The response should still terminate since a 204
527// cannot have a response body.
528TEST_F(HttpNetworkTransactionTest, StopsReading204) {
529 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35530 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
531 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42532 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17533 };
[email protected]31a2bfe2010-02-09 08:03:39534 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
535 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42536 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17537 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
538 EXPECT_EQ("", out.response_data);
539}
540
[email protected]0877e3d2009-10-17 22:29:57541// A simple request using chunked encoding with some extra data after.
542// (Like might be seen in a pipelined response.)
543TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
544 MockRead data_reads[] = {
545 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
546 MockRead("5\r\nHello\r\n"),
547 MockRead("1\r\n"),
548 MockRead(" \r\n"),
549 MockRead("5\r\nworld\r\n"),
550 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
551 MockRead(false, OK),
552 };
[email protected]31a2bfe2010-02-09 08:03:39553 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
554 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57555 EXPECT_EQ(OK, out.rv);
556 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
557 EXPECT_EQ("Hello world", out.response_data);
558}
559
[email protected]9fe44f52010-09-23 18:36:00560// Next tests deal with http://crbug.com/56344.
561
562TEST_F(HttpNetworkTransactionTest,
563 MultipleContentLengthHeadersNoTransferEncoding) {
564 MockRead data_reads[] = {
565 MockRead("HTTP/1.1 200 OK\r\n"),
566 MockRead("Content-Length: 10\r\n"),
567 MockRead("Content-Length: 5\r\n\r\n"),
568 };
569 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
570 arraysize(data_reads));
571 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
572}
573
574TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04575 DuplicateContentLengthHeadersNoTransferEncoding) {
576 MockRead data_reads[] = {
577 MockRead("HTTP/1.1 200 OK\r\n"),
578 MockRead("Content-Length: 5\r\n"),
579 MockRead("Content-Length: 5\r\n\r\n"),
580 MockRead("Hello"),
581 };
582 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
583 arraysize(data_reads));
584 EXPECT_EQ(OK, out.rv);
585 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
586 EXPECT_EQ("Hello", out.response_data);
587}
588
589TEST_F(HttpNetworkTransactionTest,
590 ComplexContentLengthHeadersNoTransferEncoding) {
591 // More than 2 dupes.
592 {
593 MockRead data_reads[] = {
594 MockRead("HTTP/1.1 200 OK\r\n"),
595 MockRead("Content-Length: 5\r\n"),
596 MockRead("Content-Length: 5\r\n"),
597 MockRead("Content-Length: 5\r\n\r\n"),
598 MockRead("Hello"),
599 };
600 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
601 arraysize(data_reads));
602 EXPECT_EQ(OK, out.rv);
603 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
604 EXPECT_EQ("Hello", out.response_data);
605 }
606 // HTTP/1.0
607 {
608 MockRead data_reads[] = {
609 MockRead("HTTP/1.0 200 OK\r\n"),
610 MockRead("Content-Length: 5\r\n"),
611 MockRead("Content-Length: 5\r\n"),
612 MockRead("Content-Length: 5\r\n\r\n"),
613 MockRead("Hello"),
614 };
615 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
616 arraysize(data_reads));
617 EXPECT_EQ(OK, out.rv);
618 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
619 EXPECT_EQ("Hello", out.response_data);
620 }
621 // 2 dupes and one mismatched.
622 {
623 MockRead data_reads[] = {
624 MockRead("HTTP/1.1 200 OK\r\n"),
625 MockRead("Content-Length: 10\r\n"),
626 MockRead("Content-Length: 10\r\n"),
627 MockRead("Content-Length: 5\r\n\r\n"),
628 };
629 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
630 arraysize(data_reads));
631 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
632 }
633}
634
635TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00636 MultipleContentLengthHeadersTransferEncoding) {
637 MockRead data_reads[] = {
638 MockRead("HTTP/1.1 200 OK\r\n"),
639 MockRead("Content-Length: 666\r\n"),
640 MockRead("Content-Length: 1337\r\n"),
641 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
642 MockRead("5\r\nHello\r\n"),
643 MockRead("1\r\n"),
644 MockRead(" \r\n"),
645 MockRead("5\r\nworld\r\n"),
646 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
647 MockRead(false, OK),
648 };
649 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
650 arraysize(data_reads));
651 EXPECT_EQ(OK, out.rv);
652 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
653 EXPECT_EQ("Hello world", out.response_data);
654}
655
[email protected]1628fe92011-10-04 23:04:55656// Next tests deal with http://crbug.com/98895.
657
658// Checks that a single Content-Disposition header results in no error.
659TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
660 MockRead data_reads[] = {
661 MockRead("HTTP/1.1 200 OK\r\n"),
662 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
663 MockRead("Content-Length: 5\r\n\r\n"),
664 MockRead("Hello"),
665 };
666 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
667 arraysize(data_reads));
668 EXPECT_EQ(OK, out.rv);
669 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
670 EXPECT_EQ("Hello", out.response_data);
671}
672
673// Checks that two identical Content-Disposition headers result in an error.
674TEST_F(HttpNetworkTransactionTest,
675 DuplicateIdenticalContentDispositionHeaders) {
676 MockRead data_reads[] = {
677 MockRead("HTTP/1.1 200 OK\r\n"),
678 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
679 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
680 MockRead("Content-Length: 5\r\n\r\n"),
681 MockRead("Hello"),
682 };
683 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
684 arraysize(data_reads));
685 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
686}
687
688// Checks that two distinct Content-Disposition headers result in an error.
689TEST_F(HttpNetworkTransactionTest, DuplicateDistinctContentDispositionHeaders) {
690 MockRead data_reads[] = {
691 MockRead("HTTP/1.1 200 OK\r\n"),
692 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
693 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
694 MockRead("Content-Length: 5\r\n\r\n"),
695 MockRead("Hello"),
696 };
697 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
698 arraysize(data_reads));
699 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
700}
701
702// Checks the behavior of a single Location header.
703TEST_F(HttpNetworkTransactionTest, SingleLocationHeader) {
704 MockRead data_reads[] = {
705 MockRead("HTTP/1.1 302 Redirect\r\n"),
706 MockRead("Location: http://good.com/\r\n"),
707 MockRead("Content-Length: 0\r\n\r\n"),
708 MockRead(false, OK),
709 };
710
711 HttpRequestInfo request;
712 request.method = "GET";
713 request.url = GURL("http://redirect.com/");
714 request.load_flags = 0;
715
716 SessionDependencies session_deps;
717 scoped_ptr<HttpTransaction> trans(
718 new HttpNetworkTransaction(CreateSession(&session_deps)));
719
720 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
721 session_deps.socket_factory.AddSocketDataProvider(&data);
722
[email protected]49639fa2011-12-20 23:22:41723 TestCompletionCallback callback;
[email protected]1628fe92011-10-04 23:04:55724
[email protected]49639fa2011-12-20 23:22:41725 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1628fe92011-10-04 23:04:55726 EXPECT_EQ(ERR_IO_PENDING, rv);
727
728 EXPECT_EQ(OK, callback.WaitForResult());
729
730 const HttpResponseInfo* response = trans->GetResponseInfo();
731 ASSERT_TRUE(response != NULL && response->headers != NULL);
732 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
733 std::string url;
734 EXPECT_TRUE(response->headers->IsRedirect(&url));
735 EXPECT_EQ("http://good.com/", url);
736}
737
738// Checks that two identical Location headers result in an error.
739TEST_F(HttpNetworkTransactionTest, DuplicateIdenticalLocationHeaders) {
740 MockRead data_reads[] = {
741 MockRead("HTTP/1.1 302 Redirect\r\n"),
742 MockRead("Location: http://good.com/\r\n"),
743 MockRead("Location: http://good.com/\r\n"),
744 MockRead("Content-Length: 0\r\n\r\n"),
745 MockRead(false, OK),
746 };
747 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
748 arraysize(data_reads));
749 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
750}
751
752// Checks that two distinct Location headers result in an error.
753TEST_F(HttpNetworkTransactionTest, DuplicateDistinctLocationHeaders) {
754 MockRead data_reads[] = {
755 MockRead("HTTP/1.1 302 Redirect\r\n"),
756 MockRead("Location: http://good.com/\r\n"),
757 MockRead("Location: http://evil.com/\r\n"),
758 MockRead("Content-Length: 0\r\n\r\n"),
759 MockRead(false, OK),
760 };
761 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
762 arraysize(data_reads));
763 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
764}
765
[email protected]ef0faf2e72009-03-05 23:27:23766// Do a request using the HEAD method. Verify that we don't try to read the
767// message body (since HEAD has none).
768TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42769 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23770 request.method = "HEAD";
771 request.url = GURL("http://www.google.com/");
772 request.load_flags = 0;
773
[email protected]cb9bf6ca2011-01-28 13:15:27774 SessionDependencies session_deps;
775 scoped_ptr<HttpTransaction> trans(
776 new HttpNetworkTransaction(CreateSession(&session_deps)));
777
[email protected]ef0faf2e72009-03-05 23:27:23778 MockWrite data_writes1[] = {
779 MockWrite("HEAD / HTTP/1.1\r\n"
780 "Host: www.google.com\r\n"
781 "Connection: keep-alive\r\n"
782 "Content-Length: 0\r\n\r\n"),
783 };
784 MockRead data_reads1[] = {
785 MockRead("HTTP/1.1 404 Not Found\r\n"),
786 MockRead("Server: Blah\r\n"),
787 MockRead("Content-Length: 1234\r\n\r\n"),
788
789 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42790 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23791 };
792
[email protected]31a2bfe2010-02-09 08:03:39793 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
794 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59795 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23796
[email protected]49639fa2011-12-20 23:22:41797 TestCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:23798
[email protected]49639fa2011-12-20 23:22:41799 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42800 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23801
802 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42803 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23804
[email protected]1c773ea12009-04-28 19:58:42805 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50806 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:23807
808 // Check that the headers got parsed.
809 EXPECT_TRUE(response->headers != NULL);
810 EXPECT_EQ(1234, response->headers->GetContentLength());
811 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
812
813 std::string server_header;
814 void* iter = NULL;
815 bool has_server_header = response->headers->EnumerateHeader(
816 &iter, "Server", &server_header);
817 EXPECT_TRUE(has_server_header);
818 EXPECT_EQ("Blah", server_header);
819
820 // Reading should give EOF right away, since there is no message body
821 // (despite non-zero content-length).
822 std::string response_data;
823 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42824 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23825 EXPECT_EQ("", response_data);
826}
827
initial.commit586acc5fe2008-07-26 22:42:52828TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59829 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27830 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52831
832 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35833 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
834 MockRead("hello"),
835 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
836 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42837 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52838 };
[email protected]31a2bfe2010-02-09 08:03:39839 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59840 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52841
[email protected]0b0bf032010-09-21 18:08:50842 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52843 "hello", "world"
844 };
845
846 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42847 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52848 request.method = "GET";
849 request.url = GURL("http://www.google.com/");
850 request.load_flags = 0;
851
[email protected]cb9bf6ca2011-01-28 13:15:27852 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
853
[email protected]49639fa2011-12-20 23:22:41854 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52855
[email protected]49639fa2011-12-20 23:22:41856 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42857 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52858
859 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42860 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52861
[email protected]1c773ea12009-04-28 19:58:42862 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50863 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52864
865 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25866 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52867
868 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57869 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42870 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25871 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52872 }
873}
874
875TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42876 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52877 request.method = "POST";
878 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42879 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52880 request.upload_data->AppendBytes("foo", 3);
881 request.load_flags = 0;
882
[email protected]cb9bf6ca2011-01-28 13:15:27883 SessionDependencies session_deps;
884 scoped_ptr<HttpTransaction> trans(
885 new HttpNetworkTransaction(CreateSession(&session_deps)));
886
initial.commit586acc5fe2008-07-26 22:42:52887 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35888 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
889 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
890 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42891 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52892 };
[email protected]31a2bfe2010-02-09 08:03:39893 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59894 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52895
[email protected]49639fa2011-12-20 23:22:41896 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52897
[email protected]49639fa2011-12-20 23:22:41898 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42899 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52900
901 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42902 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52903
[email protected]1c773ea12009-04-28 19:58:42904 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50905 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52906
907 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25908 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52909
910 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57911 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42912 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25913 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52914}
915
[email protected]3a2d3662009-03-27 03:49:14916// This test is almost the same as Ignores100 above, but the response contains
917// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57918// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14919TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42920 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14921 request.method = "GET";
922 request.url = GURL("http://www.foo.com/");
923 request.load_flags = 0;
924
[email protected]cb9bf6ca2011-01-28 13:15:27925 SessionDependencies session_deps;
926 scoped_ptr<HttpTransaction> trans(
927 new HttpNetworkTransaction(CreateSession(&session_deps)));
928
[email protected]3a2d3662009-03-27 03:49:14929 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57930 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
931 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14932 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42933 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14934 };
[email protected]31a2bfe2010-02-09 08:03:39935 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59936 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14937
[email protected]49639fa2011-12-20 23:22:41938 TestCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:14939
[email protected]49639fa2011-12-20 23:22:41940 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42941 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14942
943 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42944 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14945
[email protected]1c773ea12009-04-28 19:58:42946 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50947 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:14948
949 EXPECT_TRUE(response->headers != NULL);
950 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
951
952 std::string response_data;
953 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42954 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14955 EXPECT_EQ("hello world", response_data);
956}
957
[email protected]ee9410e72010-01-07 01:42:38958TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38959 HttpRequestInfo request;
960 request.method = "POST";
961 request.url = GURL("http://www.foo.com/");
962 request.load_flags = 0;
963
[email protected]cb9bf6ca2011-01-28 13:15:27964 SessionDependencies session_deps;
965 scoped_ptr<HttpTransaction> trans(
966 new HttpNetworkTransaction(CreateSession(&session_deps)));
967
[email protected]ee9410e72010-01-07 01:42:38968 MockRead data_reads[] = {
969 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
970 MockRead(true, 0),
971 };
[email protected]31a2bfe2010-02-09 08:03:39972 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38973 session_deps.socket_factory.AddSocketDataProvider(&data);
974
[email protected]49639fa2011-12-20 23:22:41975 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:38976
[email protected]49639fa2011-12-20 23:22:41977 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38978 EXPECT_EQ(ERR_IO_PENDING, rv);
979
980 rv = callback.WaitForResult();
981 EXPECT_EQ(OK, rv);
982
983 std::string response_data;
984 rv = ReadTransaction(trans.get(), &response_data);
985 EXPECT_EQ(OK, rv);
986 EXPECT_EQ("", response_data);
987}
988
989TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38990 HttpRequestInfo request;
991 request.method = "POST";
992 request.url = GURL("http://www.foo.com/");
993 request.load_flags = 0;
994
[email protected]cb9bf6ca2011-01-28 13:15:27995 SessionDependencies session_deps;
996 scoped_ptr<HttpTransaction> trans(
997 new HttpNetworkTransaction(CreateSession(&session_deps)));
998
[email protected]ee9410e72010-01-07 01:42:38999 MockRead data_reads[] = {
1000 MockRead(true, 0),
1001 };
[email protected]31a2bfe2010-02-09 08:03:391002 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:381003 session_deps.socket_factory.AddSocketDataProvider(&data);
1004
[email protected]49639fa2011-12-20 23:22:411005 TestCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:381006
[email protected]49639fa2011-12-20 23:22:411007 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:381008 EXPECT_EQ(ERR_IO_PENDING, rv);
1009
1010 rv = callback.WaitForResult();
1011 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
1012}
1013
[email protected]3d2a59b2008-09-26 19:44:251014void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
[email protected]202965992011-12-07 23:04:511015 const MockWrite* write_failure,
1016 const MockRead* read_failure) {
[email protected]1c773ea12009-04-28 19:58:421017 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521018 request.method = "GET";
1019 request.url = GURL("http://www.foo.com/");
1020 request.load_flags = 0;
1021
[email protected]cb9bf6ca2011-01-28 13:15:271022 SessionDependencies session_deps;
1023 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1024
[email protected]202965992011-12-07 23:04:511025 // Written data for successfully sending both requests.
1026 MockWrite data1_writes[] = {
1027 MockWrite("GET / HTTP/1.1\r\n"
1028 "Host: www.foo.com\r\n"
1029 "Connection: keep-alive\r\n\r\n"),
1030 MockWrite("GET / HTTP/1.1\r\n"
1031 "Host: www.foo.com\r\n"
1032 "Connection: keep-alive\r\n\r\n")
1033 };
1034
1035 // Read results for the first request.
initial.commit586acc5fe2008-07-26 22:42:521036 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351037 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1038 MockRead("hello"),
[email protected]202965992011-12-07 23:04:511039 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:521040 };
[email protected]202965992011-12-07 23:04:511041
1042 if (write_failure) {
1043 ASSERT_TRUE(!read_failure);
1044 data1_writes[1] = *write_failure;
1045 } else {
1046 ASSERT_TRUE(read_failure);
1047 data1_reads[2] = *read_failure;
1048 }
1049
1050 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads),
1051 data1_writes, arraysize(data1_writes));
[email protected]5ecc992a42009-11-11 01:41:591052 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521053
1054 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351055 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1056 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:421057 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:521058 };
[email protected]31a2bfe2010-02-09 08:03:391059 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591060 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521061
1062 const char* kExpectedResponseData[] = {
1063 "hello", "world"
1064 };
1065
1066 for (int i = 0; i < 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411067 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521068
[email protected]5695b8c2009-09-30 21:36:431069 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:521070
[email protected]49639fa2011-12-20 23:22:411071 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421072 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521073
1074 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421075 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521076
[email protected]1c773ea12009-04-28 19:58:421077 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501078 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521079
1080 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:251081 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521082
1083 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571084 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421085 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251086 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521087 }
1088}
[email protected]3d2a59b2008-09-26 19:44:251089
[email protected]202965992011-12-07 23:04:511090TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionNotConnectedOnWrite) {
1091 MockWrite write_failure(true, ERR_SOCKET_NOT_CONNECTED);
1092 KeepAliveConnectionResendRequestTest(&write_failure, NULL);
1093}
1094
[email protected]3d2a59b2008-09-26 19:44:251095TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421096 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]202965992011-12-07 23:04:511097 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251098}
1099
1100TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:421101 MockRead read_failure(false, OK); // EOF
[email protected]202965992011-12-07 23:04:511102 KeepAliveConnectionResendRequestTest(NULL, &read_failure);
[email protected]3d2a59b2008-09-26 19:44:251103}
1104
1105TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421106 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251107 request.method = "GET";
1108 request.url = GURL("http://www.google.com/");
1109 request.load_flags = 0;
1110
[email protected]cb9bf6ca2011-01-28 13:15:271111 SessionDependencies session_deps;
1112 scoped_ptr<HttpTransaction> trans(
1113 new HttpNetworkTransaction(CreateSession(&session_deps)));
1114
[email protected]3d2a59b2008-09-26 19:44:251115 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421116 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351117 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1118 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:421119 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:251120 };
[email protected]31a2bfe2010-02-09 08:03:391121 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591122 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251123
[email protected]49639fa2011-12-20 23:22:411124 TestCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251125
[email protected]49639fa2011-12-20 23:22:411126 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421127 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251128
1129 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421130 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:251131
[email protected]1c773ea12009-04-28 19:58:421132 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:251133 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:251134}
1135
1136// What do various browsers do when the server closes a non-keepalive
1137// connection without sending any response header or body?
1138//
1139// IE7: error page
1140// Safari 3.1.2 (Windows): error page
1141// Firefox 3.0.1: blank page
1142// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421143// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1144// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:251145TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1146 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421147 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:351148 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1149 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:421150 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:251151 };
[email protected]31a2bfe2010-02-09 08:03:391152 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1153 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421154 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251155}
[email protected]038e9a32008-10-08 22:40:161156
[email protected]0b0bf032010-09-21 18:08:501157// Test that we correctly reuse a keep-alive connection after not explicitly
1158// reading the body.
1159TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131160 HttpRequestInfo request;
1161 request.method = "GET";
1162 request.url = GURL("http://www.foo.com/");
1163 request.load_flags = 0;
1164
[email protected]cb9bf6ca2011-01-28 13:15:271165 SessionDependencies session_deps;
1166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1167
[email protected]0b0bf032010-09-21 18:08:501168 // Note that because all these reads happen in the same
1169 // StaticSocketDataProvider, it shows that the same socket is being reused for
1170 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:131171 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:501172 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1173 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:131174 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:501175 MockRead("HTTP/1.1 302 Found\r\n"
1176 "Content-Length: 0\r\n\r\n"),
1177 MockRead("HTTP/1.1 302 Found\r\n"
1178 "Content-Length: 5\r\n\r\n"
1179 "hello"),
1180 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1181 "Content-Length: 0\r\n\r\n"),
1182 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1183 "Content-Length: 5\r\n\r\n"
1184 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131185 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1186 MockRead("hello"),
1187 };
1188 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1189 session_deps.socket_factory.AddSocketDataProvider(&data1);
1190
1191 MockRead data2_reads[] = {
1192 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
1193 };
1194 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1195 session_deps.socket_factory.AddSocketDataProvider(&data2);
1196
[email protected]0b0bf032010-09-21 18:08:501197 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1198 std::string response_lines[kNumUnreadBodies];
1199
1200 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]49639fa2011-12-20 23:22:411201 TestCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131202
1203 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1204
[email protected]49639fa2011-12-20 23:22:411205 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]fc31d6a42010-06-24 18:05:131206 EXPECT_EQ(ERR_IO_PENDING, rv);
1207
1208 rv = callback.WaitForResult();
1209 EXPECT_EQ(OK, rv);
1210
1211 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501212 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131213
[email protected]0b0bf032010-09-21 18:08:501214 ASSERT_TRUE(response->headers != NULL);
1215 response_lines[i] = response->headers->GetStatusLine();
1216
1217 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131218 }
[email protected]0b0bf032010-09-21 18:08:501219
1220 const char* const kStatusLines[] = {
1221 "HTTP/1.1 204 No Content",
1222 "HTTP/1.1 205 Reset Content",
1223 "HTTP/1.1 304 Not Modified",
1224 "HTTP/1.1 302 Found",
1225 "HTTP/1.1 302 Found",
1226 "HTTP/1.1 301 Moved Permanently",
1227 "HTTP/1.1 301 Moved Permanently",
1228 };
1229
1230 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1231 forgot_to_update_kStatusLines);
1232
1233 for (int i = 0; i < kNumUnreadBodies; ++i)
1234 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1235
[email protected]49639fa2011-12-20 23:22:411236 TestCompletionCallback callback;
[email protected]0b0bf032010-09-21 18:08:501237 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411238 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0b0bf032010-09-21 18:08:501239 EXPECT_EQ(ERR_IO_PENDING, rv);
1240 rv = callback.WaitForResult();
1241 EXPECT_EQ(OK, rv);
1242 const HttpResponseInfo* response = trans->GetResponseInfo();
1243 ASSERT_TRUE(response != NULL);
1244 ASSERT_TRUE(response->headers != NULL);
1245 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1246 std::string response_data;
1247 rv = ReadTransaction(trans.get(), &response_data);
1248 EXPECT_EQ(OK, rv);
1249 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131250}
1251
[email protected]038e9a32008-10-08 22:40:161252// Test the request-challenge-retry sequence for basic auth.
1253// (basic auth is the easiest to mock, because it has no randomness).
1254TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421255 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161256 request.method = "GET";
1257 request.url = GURL("http://www.google.com/");
1258 request.load_flags = 0;
1259
[email protected]cb9bf6ca2011-01-28 13:15:271260 SessionDependencies session_deps;
1261 scoped_ptr<HttpTransaction> trans(
1262 new HttpNetworkTransaction(CreateSession(&session_deps)));
1263
[email protected]f9ee6b52008-11-08 06:46:231264 MockWrite data_writes1[] = {
1265 MockWrite("GET / HTTP/1.1\r\n"
1266 "Host: www.google.com\r\n"
1267 "Connection: keep-alive\r\n\r\n"),
1268 };
1269
[email protected]038e9a32008-10-08 22:40:161270 MockRead data_reads1[] = {
1271 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1272 // Give a couple authenticate options (only the middle one is actually
1273 // supported).
[email protected]22927ad2009-09-21 19:56:191274 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161275 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1276 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1277 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1278 // Large content-length -- won't matter, as connection will be reset.
1279 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421280 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161281 };
1282
1283 // After calling trans->RestartWithAuth(), this is the request we should
1284 // be issuing -- the final header line contains the credentials.
1285 MockWrite data_writes2[] = {
1286 MockWrite("GET / HTTP/1.1\r\n"
1287 "Host: www.google.com\r\n"
1288 "Connection: keep-alive\r\n"
1289 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1290 };
1291
1292 // Lastly, the server responds with the actual content.
1293 MockRead data_reads2[] = {
1294 MockRead("HTTP/1.0 200 OK\r\n"),
1295 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1296 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421297 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161298 };
1299
[email protected]31a2bfe2010-02-09 08:03:391300 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1301 data_writes1, arraysize(data_writes1));
1302 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1303 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591304 session_deps.socket_factory.AddSocketDataProvider(&data1);
1305 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161306
[email protected]49639fa2011-12-20 23:22:411307 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:161308
[email protected]49639fa2011-12-20 23:22:411309 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421310 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161311
1312 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421313 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161314
[email protected]1c773ea12009-04-28 19:58:421315 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501316 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041317 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:161318
[email protected]49639fa2011-12-20 23:22:411319 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:161320
[email protected]49639fa2011-12-20 23:22:411321 rv = trans->RestartWithAuth(
1322 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421323 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161324
1325 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421326 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161327
1328 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501329 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:161330 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1331 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161332}
1333
[email protected]861fcd52009-08-26 02:33:461334TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461335 HttpRequestInfo request;
1336 request.method = "GET";
1337 request.url = GURL("http://www.google.com/");
1338 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1339
[email protected]cb9bf6ca2011-01-28 13:15:271340 SessionDependencies session_deps;
1341 scoped_ptr<HttpTransaction> trans(
1342 new HttpNetworkTransaction(CreateSession(&session_deps)));
1343
[email protected]861fcd52009-08-26 02:33:461344 MockWrite data_writes[] = {
1345 MockWrite("GET / HTTP/1.1\r\n"
1346 "Host: www.google.com\r\n"
1347 "Connection: keep-alive\r\n\r\n"),
1348 };
1349
1350 MockRead data_reads[] = {
1351 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1352 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1353 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1354 // Large content-length -- won't matter, as connection will be reset.
1355 MockRead("Content-Length: 10000\r\n\r\n"),
1356 MockRead(false, ERR_FAILED),
1357 };
1358
[email protected]31a2bfe2010-02-09 08:03:391359 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1360 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591361 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]49639fa2011-12-20 23:22:411362 TestCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:461363
[email protected]49639fa2011-12-20 23:22:411364 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461365 EXPECT_EQ(ERR_IO_PENDING, rv);
1366
1367 rv = callback.WaitForResult();
1368 EXPECT_EQ(0, rv);
1369
1370 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501371 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:461372 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1373}
1374
[email protected]2d2697f92009-02-18 21:00:321375// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1376// connection.
1377TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421378 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321379 request.method = "GET";
1380 request.url = GURL("http://www.google.com/");
1381 request.load_flags = 0;
1382
[email protected]cb9bf6ca2011-01-28 13:15:271383 SessionDependencies session_deps;
1384 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1385
[email protected]2d2697f92009-02-18 21:00:321386 MockWrite data_writes1[] = {
1387 MockWrite("GET / HTTP/1.1\r\n"
1388 "Host: www.google.com\r\n"
1389 "Connection: keep-alive\r\n\r\n"),
1390
1391 // After calling trans->RestartWithAuth(), this is the request we should
1392 // be issuing -- the final header line contains the credentials.
1393 MockWrite("GET / HTTP/1.1\r\n"
1394 "Host: www.google.com\r\n"
1395 "Connection: keep-alive\r\n"
1396 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1397 };
1398
1399 MockRead data_reads1[] = {
1400 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1401 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1402 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1403 MockRead("Content-Length: 14\r\n\r\n"),
1404 MockRead("Unauthorized\r\n"),
1405
1406 // Lastly, the server responds with the actual content.
1407 MockRead("HTTP/1.1 200 OK\r\n"),
1408 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501409 MockRead("Content-Length: 5\r\n\r\n"),
1410 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321411 };
1412
[email protected]2d0a4f92011-05-05 16:38:461413 // If there is a regression where we disconnect a Keep-Alive
1414 // connection during an auth roundtrip, we'll end up reading this.
1415 MockRead data_reads2[] = {
1416 MockRead(false, ERR_FAILED),
1417 };
1418
[email protected]31a2bfe2010-02-09 08:03:391419 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1420 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461421 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1422 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591423 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461424 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321425
[email protected]49639fa2011-12-20 23:22:411426 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321427
[email protected]0b0bf032010-09-21 18:08:501428 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411429 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421430 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321431
1432 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421433 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321434
[email protected]1c773ea12009-04-28 19:58:421435 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501436 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041437 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321438
[email protected]49639fa2011-12-20 23:22:411439 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321440
[email protected]49639fa2011-12-20 23:22:411441 rv = trans->RestartWithAuth(
1442 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421443 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321444
1445 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421446 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321447
1448 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501449 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321450 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501451 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321452}
1453
1454// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1455// connection and with no response body to drain.
1456TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421457 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321458 request.method = "GET";
1459 request.url = GURL("http://www.google.com/");
1460 request.load_flags = 0;
1461
[email protected]cb9bf6ca2011-01-28 13:15:271462 SessionDependencies session_deps;
1463 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1464
[email protected]2d2697f92009-02-18 21:00:321465 MockWrite data_writes1[] = {
1466 MockWrite("GET / HTTP/1.1\r\n"
1467 "Host: www.google.com\r\n"
1468 "Connection: keep-alive\r\n\r\n"),
1469
1470 // After calling trans->RestartWithAuth(), this is the request we should
1471 // be issuing -- the final header line contains the credentials.
1472 MockWrite("GET / HTTP/1.1\r\n"
1473 "Host: www.google.com\r\n"
1474 "Connection: keep-alive\r\n"
1475 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1476 };
1477
[email protected]2d2697f92009-02-18 21:00:321478 MockRead data_reads1[] = {
1479 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1480 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311481 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321482
1483 // Lastly, the server responds with the actual content.
1484 MockRead("HTTP/1.1 200 OK\r\n"),
1485 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501486 MockRead("Content-Length: 5\r\n\r\n"),
1487 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321488 };
1489
[email protected]2d0a4f92011-05-05 16:38:461490 // An incorrect reconnect would cause this to be read.
1491 MockRead data_reads2[] = {
1492 MockRead(false, ERR_FAILED),
1493 };
1494
[email protected]31a2bfe2010-02-09 08:03:391495 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1496 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461497 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1498 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591499 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461500 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321501
[email protected]49639fa2011-12-20 23:22:411502 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321503
[email protected]0b0bf032010-09-21 18:08:501504 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411505 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421506 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321507
1508 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421509 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321510
[email protected]1c773ea12009-04-28 19:58:421511 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501512 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041513 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321514
[email protected]49639fa2011-12-20 23:22:411515 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321516
[email protected]49639fa2011-12-20 23:22:411517 rv = trans->RestartWithAuth(
1518 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421519 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321520
1521 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421522 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321523
1524 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501525 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321526 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501527 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321528}
1529
1530// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1531// connection and with a large response body to drain.
1532TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421533 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321534 request.method = "GET";
1535 request.url = GURL("http://www.google.com/");
1536 request.load_flags = 0;
1537
[email protected]cb9bf6ca2011-01-28 13:15:271538 SessionDependencies session_deps;
1539 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1540
[email protected]2d2697f92009-02-18 21:00:321541 MockWrite data_writes1[] = {
1542 MockWrite("GET / HTTP/1.1\r\n"
1543 "Host: www.google.com\r\n"
1544 "Connection: keep-alive\r\n\r\n"),
1545
1546 // After calling trans->RestartWithAuth(), this is the request we should
1547 // be issuing -- the final header line contains the credentials.
1548 MockWrite("GET / HTTP/1.1\r\n"
1549 "Host: www.google.com\r\n"
1550 "Connection: keep-alive\r\n"
1551 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1552 };
1553
1554 // Respond with 5 kb of response body.
1555 std::string large_body_string("Unauthorized");
1556 large_body_string.append(5 * 1024, ' ');
1557 large_body_string.append("\r\n");
1558
1559 MockRead data_reads1[] = {
1560 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1561 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1562 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1563 // 5134 = 12 + 5 * 1024 + 2
1564 MockRead("Content-Length: 5134\r\n\r\n"),
1565 MockRead(true, large_body_string.data(), large_body_string.size()),
1566
1567 // Lastly, the server responds with the actual content.
1568 MockRead("HTTP/1.1 200 OK\r\n"),
1569 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501570 MockRead("Content-Length: 5\r\n\r\n"),
1571 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321572 };
1573
[email protected]2d0a4f92011-05-05 16:38:461574 // An incorrect reconnect would cause this to be read.
1575 MockRead data_reads2[] = {
1576 MockRead(false, ERR_FAILED),
1577 };
1578
[email protected]31a2bfe2010-02-09 08:03:391579 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1580 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461581 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1582 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591583 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461584 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321585
[email protected]49639fa2011-12-20 23:22:411586 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321587
[email protected]0b0bf032010-09-21 18:08:501588 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411589 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421590 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321591
1592 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421593 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321594
[email protected]1c773ea12009-04-28 19:58:421595 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501596 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041597 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321598
[email protected]49639fa2011-12-20 23:22:411599 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321600
[email protected]49639fa2011-12-20 23:22:411601 rv = trans->RestartWithAuth(
1602 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421603 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321604
1605 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421606 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321607
1608 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501609 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321610 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501611 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321612}
1613
1614// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311615// connection, but the server gets impatient and closes the connection.
1616TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311617 HttpRequestInfo request;
1618 request.method = "GET";
1619 request.url = GURL("http://www.google.com/");
1620 request.load_flags = 0;
1621
[email protected]cb9bf6ca2011-01-28 13:15:271622 SessionDependencies session_deps;
1623 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1624
[email protected]11203f012009-11-12 23:02:311625 MockWrite data_writes1[] = {
1626 MockWrite("GET / HTTP/1.1\r\n"
1627 "Host: www.google.com\r\n"
1628 "Connection: keep-alive\r\n\r\n"),
1629 // This simulates the seemingly successful write to a closed connection
1630 // if the bug is not fixed.
1631 MockWrite("GET / HTTP/1.1\r\n"
1632 "Host: www.google.com\r\n"
1633 "Connection: keep-alive\r\n"
1634 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1635 };
1636
1637 MockRead data_reads1[] = {
1638 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1639 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1640 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1641 MockRead("Content-Length: 14\r\n\r\n"),
1642 // Tell MockTCPClientSocket to simulate the server closing the connection.
1643 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1644 MockRead("Unauthorized\r\n"),
1645 MockRead(false, OK), // The server closes the connection.
1646 };
1647
1648 // After calling trans->RestartWithAuth(), this is the request we should
1649 // be issuing -- the final header line contains the credentials.
1650 MockWrite data_writes2[] = {
1651 MockWrite("GET / HTTP/1.1\r\n"
1652 "Host: www.google.com\r\n"
1653 "Connection: keep-alive\r\n"
1654 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1655 };
1656
1657 // Lastly, the server responds with the actual content.
1658 MockRead data_reads2[] = {
1659 MockRead("HTTP/1.1 200 OK\r\n"),
1660 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501661 MockRead("Content-Length: 5\r\n\r\n"),
1662 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311663 };
1664
[email protected]31a2bfe2010-02-09 08:03:391665 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1666 data_writes1, arraysize(data_writes1));
1667 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1668 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311669 session_deps.socket_factory.AddSocketDataProvider(&data1);
1670 session_deps.socket_factory.AddSocketDataProvider(&data2);
1671
[email protected]49639fa2011-12-20 23:22:411672 TestCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:311673
[email protected]0b0bf032010-09-21 18:08:501674 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:411675 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]11203f012009-11-12 23:02:311676 EXPECT_EQ(ERR_IO_PENDING, rv);
1677
1678 rv = callback1.WaitForResult();
1679 EXPECT_EQ(OK, rv);
1680
1681 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501682 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041683 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:311684
[email protected]49639fa2011-12-20 23:22:411685 TestCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:311686
[email protected]49639fa2011-12-20 23:22:411687 rv = trans->RestartWithAuth(
1688 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]11203f012009-11-12 23:02:311689 EXPECT_EQ(ERR_IO_PENDING, rv);
1690
1691 rv = callback2.WaitForResult();
1692 EXPECT_EQ(OK, rv);
1693
1694 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501695 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:311696 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501697 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311698}
1699
[email protected]394816e92010-08-03 07:38:591700// Test the request-challenge-retry sequence for basic auth, over a connection
1701// that requires a restart when setting up an SSL tunnel.
1702TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591703 HttpRequestInfo request;
1704 request.method = "GET";
1705 request.url = GURL("https://www.google.com/");
1706 // when the no authentication data flag is set.
1707 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1708
[email protected]cb9bf6ca2011-01-28 13:15:271709 // Configure against proxy server "myproxy:70".
1710 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1711 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1712 session_deps.net_log = log.bound().net_log();
1713 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1714
[email protected]394816e92010-08-03 07:38:591715 // Since we have proxy, should try to establish tunnel.
1716 MockWrite data_writes1[] = {
1717 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1718 "Host: www.google.com\r\n"
1719 "Proxy-Connection: keep-alive\r\n\r\n"),
1720
1721 // After calling trans->RestartWithAuth(), this is the request we should
1722 // be issuing -- the final header line contains the credentials.
1723 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1724 "Host: www.google.com\r\n"
1725 "Proxy-Connection: keep-alive\r\n"
1726 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1727
1728 MockWrite("GET / HTTP/1.1\r\n"
1729 "Host: www.google.com\r\n"
1730 "Connection: keep-alive\r\n\r\n"),
1731 };
1732
1733 // The proxy responds to the connect with a 407, using a persistent
1734 // connection.
1735 MockRead data_reads1[] = {
1736 // No credentials.
1737 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1738 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1739 MockRead("Proxy-Connection: close\r\n\r\n"),
1740
1741 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1742
1743 MockRead("HTTP/1.1 200 OK\r\n"),
1744 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501745 MockRead("Content-Length: 5\r\n\r\n"),
1746 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591747 };
1748
1749 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1750 data_writes1, arraysize(data_writes1));
1751 session_deps.socket_factory.AddSocketDataProvider(&data1);
1752 SSLSocketDataProvider ssl(true, OK);
1753 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1754
[email protected]49639fa2011-12-20 23:22:411755 TestCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:591756
[email protected]0b0bf032010-09-21 18:08:501757 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1758
[email protected]49639fa2011-12-20 23:22:411759 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]394816e92010-08-03 07:38:591760 EXPECT_EQ(ERR_IO_PENDING, rv);
1761
1762 rv = callback1.WaitForResult();
1763 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401764 net::CapturingNetLog::EntryList entries;
1765 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591766 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401767 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591768 NetLog::PHASE_NONE);
1769 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401770 entries, pos,
[email protected]394816e92010-08-03 07:38:591771 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1772 NetLog::PHASE_NONE);
1773
1774 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501775 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041776 ASSERT_FALSE(response->headers == NULL);
[email protected]394816e92010-08-03 07:38:591777 EXPECT_EQ(407, response->headers->response_code());
1778 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041779 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:591780
[email protected]49639fa2011-12-20 23:22:411781 TestCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:591782
[email protected]49639fa2011-12-20 23:22:411783 rv = trans->RestartWithAuth(
1784 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]394816e92010-08-03 07:38:591785 EXPECT_EQ(ERR_IO_PENDING, rv);
1786
1787 rv = callback2.WaitForResult();
1788 EXPECT_EQ(OK, rv);
1789
1790 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501791 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:591792
1793 EXPECT_TRUE(response->headers->IsKeepAlive());
1794 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501795 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591796 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1797
1798 // The password prompt info should not be set.
1799 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501800
1801 trans.reset();
[email protected]102e27c2011-02-23 01:01:311802 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591803}
1804
[email protected]11203f012009-11-12 23:02:311805// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321806// proxy connection, when setting up an SSL tunnel.
1807TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271808 HttpRequestInfo request;
1809 request.method = "GET";
1810 request.url = GURL("https://www.google.com/");
1811 // Ensure that proxy authentication is attempted even
1812 // when the no authentication data flag is set.
1813 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1814
[email protected]2d2697f92009-02-18 21:00:321815 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001816 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541817 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1818 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591819 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321820
[email protected]5695b8c2009-09-30 21:36:431821 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321822
[email protected]2d2697f92009-02-18 21:00:321823 // Since we have proxy, should try to establish tunnel.
1824 MockWrite data_writes1[] = {
1825 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451826 "Host: www.google.com\r\n"
1827 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321828
1829 // After calling trans->RestartWithAuth(), this is the request we should
1830 // be issuing -- the final header line contains the credentials.
1831 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1832 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451833 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321834 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1835 };
1836
1837 // The proxy responds to the connect with a 407, using a persistent
1838 // connection.
1839 MockRead data_reads1[] = {
1840 // No credentials.
1841 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1842 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1843 MockRead("Content-Length: 10\r\n\r\n"),
1844 MockRead("0123456789"),
1845
1846 // Wrong credentials (wrong password).
1847 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1848 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1849 MockRead("Content-Length: 10\r\n\r\n"),
1850 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421851 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321852 };
1853
[email protected]31a2bfe2010-02-09 08:03:391854 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1855 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591856 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321857
[email protected]49639fa2011-12-20 23:22:411858 TestCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321859
[email protected]49639fa2011-12-20 23:22:411860 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]1c773ea12009-04-28 19:58:421861 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321862
1863 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421864 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401865 net::CapturingNetLog::EntryList entries;
1866 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391867 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401868 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391869 NetLog::PHASE_NONE);
1870 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401871 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391872 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1873 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321874
[email protected]1c773ea12009-04-28 19:58:421875 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501876 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041877 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321878 EXPECT_TRUE(response->headers->IsKeepAlive());
1879 EXPECT_EQ(407, response->headers->response_code());
1880 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421881 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041882 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321883
[email protected]49639fa2011-12-20 23:22:411884 TestCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321885
1886 // Wrong password (should be "bar").
[email protected]49639fa2011-12-20 23:22:411887 rv = trans->RestartWithAuth(
1888 AuthCredentials(kFoo, kBaz), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:421889 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321890
1891 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421892 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321893
1894 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501895 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041896 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321897 EXPECT_TRUE(response->headers->IsKeepAlive());
1898 EXPECT_EQ(407, response->headers->response_code());
1899 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421900 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041901 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]e772db3f2010-07-12 18:11:131902
[email protected]e60e47a2010-07-14 03:37:181903 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1904 // out of scope.
[email protected]102e27c2011-02-23 01:01:311905 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321906}
1907
[email protected]a8e9b162009-03-12 00:06:441908// Test that we don't read the response body when we fail to establish a tunnel,
1909// even if the user cancels the proxy's auth attempt.
1910TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271911 HttpRequestInfo request;
1912 request.method = "GET";
1913 request.url = GURL("https://www.google.com/");
1914 request.load_flags = 0;
1915
[email protected]a8e9b162009-03-12 00:06:441916 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001917 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441918
[email protected]e44de5d2009-06-05 20:12:451919 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441920
[email protected]5695b8c2009-09-30 21:36:431921 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441922
[email protected]a8e9b162009-03-12 00:06:441923 // Since we have proxy, should try to establish tunnel.
1924 MockWrite data_writes[] = {
1925 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451926 "Host: www.google.com\r\n"
1927 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441928 };
1929
1930 // The proxy responds to the connect with a 407.
1931 MockRead data_reads[] = {
1932 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1933 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1934 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421935 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441936 };
1937
[email protected]31a2bfe2010-02-09 08:03:391938 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1939 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591940 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441941
[email protected]49639fa2011-12-20 23:22:411942 TestCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:441943
[email protected]49639fa2011-12-20 23:22:411944 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421945 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441946
1947 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421948 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441949
[email protected]1c773ea12009-04-28 19:58:421950 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501951 ASSERT_TRUE(response != NULL);
[email protected]a8e9b162009-03-12 00:06:441952
1953 EXPECT_TRUE(response->headers->IsKeepAlive());
1954 EXPECT_EQ(407, response->headers->response_code());
1955 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421956 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441957
1958 std::string response_data;
1959 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421960 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181961
1962 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311963 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441964}
1965
[email protected]8fdbcd22010-05-05 02:54:521966// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1967// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1968TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521969 HttpRequestInfo request;
1970 request.method = "GET";
1971 request.url = GURL("http://www.google.com/");
1972 request.load_flags = 0;
1973
[email protected]cb9bf6ca2011-01-28 13:15:271974 // We are using a DIRECT connection (i.e. no proxy) for this session.
1975 SessionDependencies session_deps;
1976 scoped_ptr<HttpTransaction> trans(
1977 new HttpNetworkTransaction(CreateSession(&session_deps)));
1978
[email protected]8fdbcd22010-05-05 02:54:521979 MockWrite data_writes1[] = {
1980 MockWrite("GET / HTTP/1.1\r\n"
1981 "Host: www.google.com\r\n"
1982 "Connection: keep-alive\r\n\r\n"),
1983 };
1984
1985 MockRead data_reads1[] = {
1986 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1987 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1988 // Large content-length -- won't matter, as connection will be reset.
1989 MockRead("Content-Length: 10000\r\n\r\n"),
1990 MockRead(false, ERR_FAILED),
1991 };
1992
1993 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1994 data_writes1, arraysize(data_writes1));
1995 session_deps.socket_factory.AddSocketDataProvider(&data1);
1996
[email protected]49639fa2011-12-20 23:22:411997 TestCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:521998
[email protected]49639fa2011-12-20 23:22:411999 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]8fdbcd22010-05-05 02:54:522000 EXPECT_EQ(ERR_IO_PENDING, rv);
2001
2002 rv = callback.WaitForResult();
2003 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
2004}
2005
[email protected]7a67a8152010-11-05 18:31:102006// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
2007// through a non-authenticating proxy. The request should fail with
2008// ERR_UNEXPECTED_PROXY_AUTH.
2009// Note that it is impossible to detect if an HTTP server returns a 407 through
2010// a non-authenticating proxy - there is nothing to indicate whether the
2011// response came from the proxy or the server, so it is treated as if the proxy
2012// issued the challenge.
2013TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:272014 HttpRequestInfo request;
2015 request.method = "GET";
2016 request.url = GURL("https://www.google.com/");
2017
[email protected]7a67a8152010-11-05 18:31:102018 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2019 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2020 session_deps.net_log = log.bound().net_log();
2021 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2022
[email protected]7a67a8152010-11-05 18:31:102023 // Since we have proxy, should try to establish tunnel.
2024 MockWrite data_writes1[] = {
2025 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
2026 "Host: www.google.com\r\n"
2027 "Proxy-Connection: keep-alive\r\n\r\n"),
2028
2029 MockWrite("GET / HTTP/1.1\r\n"
2030 "Host: www.google.com\r\n"
2031 "Connection: keep-alive\r\n\r\n"),
2032 };
2033
2034 MockRead data_reads1[] = {
2035 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
2036
2037 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
2038 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2039 MockRead("\r\n"),
2040 MockRead(false, OK),
2041 };
2042
2043 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2044 data_writes1, arraysize(data_writes1));
2045 session_deps.socket_factory.AddSocketDataProvider(&data1);
2046 SSLSocketDataProvider ssl(true, OK);
2047 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2048
[email protected]49639fa2011-12-20 23:22:412049 TestCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:102050
2051 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2052
[email protected]49639fa2011-12-20 23:22:412053 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7a67a8152010-11-05 18:31:102054 EXPECT_EQ(ERR_IO_PENDING, rv);
2055
2056 rv = callback1.WaitForResult();
2057 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:402058 net::CapturingNetLog::EntryList entries;
2059 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:102060 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402061 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:102062 NetLog::PHASE_NONE);
2063 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402064 entries, pos,
[email protected]7a67a8152010-11-05 18:31:102065 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2066 NetLog::PHASE_NONE);
2067}
[email protected]2df19bb2010-08-25 20:13:462068
2069// Test a simple get through an HTTPS Proxy.
2070TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272071 HttpRequestInfo request;
2072 request.method = "GET";
2073 request.url = GURL("http://www.google.com/");
2074
[email protected]2df19bb2010-08-25 20:13:462075 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112076 SessionDependencies session_deps(ProxyService::CreateFixed(
2077 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462078 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2079 session_deps.net_log = log.bound().net_log();
2080 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2081
[email protected]2df19bb2010-08-25 20:13:462082 // Since we have proxy, should use full url
2083 MockWrite data_writes1[] = {
2084 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2085 "Host: www.google.com\r\n"
2086 "Proxy-Connection: keep-alive\r\n\r\n"),
2087 };
2088
2089 MockRead data_reads1[] = {
2090 MockRead("HTTP/1.1 200 OK\r\n"),
2091 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2092 MockRead("Content-Length: 100\r\n\r\n"),
2093 MockRead(false, OK),
2094 };
2095
2096 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2097 data_writes1, arraysize(data_writes1));
2098 session_deps.socket_factory.AddSocketDataProvider(&data1);
2099 SSLSocketDataProvider ssl(true, OK);
2100 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2101
[email protected]49639fa2011-12-20 23:22:412102 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462103
[email protected]0b0bf032010-09-21 18:08:502104 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2105
[email protected]49639fa2011-12-20 23:22:412106 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:462107 EXPECT_EQ(ERR_IO_PENDING, rv);
2108
2109 rv = callback1.WaitForResult();
2110 EXPECT_EQ(OK, rv);
2111
2112 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502113 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462114
2115 EXPECT_TRUE(response->headers->IsKeepAlive());
2116 EXPECT_EQ(200, response->headers->response_code());
2117 EXPECT_EQ(100, response->headers->GetContentLength());
2118 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2119
2120 // The password prompt info should not be set.
2121 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2122}
2123
[email protected]7642b5ae2010-09-01 20:55:172124// Test a SPDY get through an HTTPS Proxy.
2125TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272126 HttpRequestInfo request;
2127 request.method = "GET";
2128 request.url = GURL("http://www.google.com/");
2129 request.load_flags = 0;
2130
[email protected]7642b5ae2010-09-01 20:55:172131 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112132 SessionDependencies session_deps(ProxyService::CreateFixed(
2133 "https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:172134 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2135 session_deps.net_log = log.bound().net_log();
2136 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2137
[email protected]7642b5ae2010-09-01 20:55:172138 // fetch http://www.google.com/ via SPDY
2139 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
2140 false));
2141 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2142
2143 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2144 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2145 MockRead spdy_reads[] = {
2146 CreateMockRead(*resp),
2147 CreateMockRead(*data),
2148 MockRead(true, 0, 0),
2149 };
2150
[email protected]a1595312012-01-22 03:25:042151 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]7642b5ae2010-09-01 20:55:172152 new DelayedSocketData(
2153 1, // wait for one write to finish before reading.
2154 spdy_reads, arraysize(spdy_reads),
2155 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042156 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]7642b5ae2010-09-01 20:55:172157
2158 SSLSocketDataProvider ssl(true, OK);
2159 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202160 ssl.next_proto = "spdy/2.1";
[email protected]7642b5ae2010-09-01 20:55:172161 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202162 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]7642b5ae2010-09-01 20:55:172163 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2164
[email protected]49639fa2011-12-20 23:22:412165 TestCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:172166
[email protected]0b0bf032010-09-21 18:08:502167 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2168
[email protected]49639fa2011-12-20 23:22:412169 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]7642b5ae2010-09-01 20:55:172170 EXPECT_EQ(ERR_IO_PENDING, rv);
2171
2172 rv = callback1.WaitForResult();
2173 EXPECT_EQ(OK, rv);
2174
2175 const HttpResponseInfo* response = trans->GetResponseInfo();
2176 ASSERT_TRUE(response != NULL);
2177 ASSERT_TRUE(response->headers != NULL);
2178 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2179
2180 std::string response_data;
2181 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2182 EXPECT_EQ(net::kUploadData, response_data);
2183}
2184
[email protected]dc7bd1c52010-11-12 00:01:132185// Test a SPDY get through an HTTPS Proxy.
2186TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272187 HttpRequestInfo request;
2188 request.method = "GET";
2189 request.url = GURL("http://www.google.com/");
2190 request.load_flags = 0;
2191
[email protected]79cb5c12011-09-12 13:12:042192 // Configure against https proxy server "myproxy:70".
[email protected]dc7bd1c52010-11-12 00:01:132193 SessionDependencies session_deps(
[email protected]79cb5c12011-09-12 13:12:042194 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]dc7bd1c52010-11-12 00:01:132195 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2196 session_deps.net_log = log.bound().net_log();
2197 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2198
[email protected]dc7bd1c52010-11-12 00:01:132199 // The first request will be a bare GET, the second request will be a
2200 // GET with a Proxy-Authorization header.
2201 scoped_ptr<spdy::SpdyFrame> req_get(
2202 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2203 const char* const kExtraAuthorizationHeaders[] = {
2204 "proxy-authorization",
2205 "Basic Zm9vOmJhcg==",
2206 };
2207 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2208 ConstructSpdyGet(
2209 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2210 false, 3, LOWEST, false));
2211 MockWrite spdy_writes[] = {
2212 CreateMockWrite(*req_get, 1),
2213 CreateMockWrite(*req_get_authorization, 4),
2214 };
2215
2216 // The first response is a 407 proxy authentication challenge, and the second
2217 // response will be a 200 response since the second request includes a valid
2218 // Authorization header.
2219 const char* const kExtraAuthenticationHeaders[] = {
2220 "Proxy-Authenticate",
2221 "Basic realm=\"MyRealm1\""
2222 };
2223 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2224 ConstructSpdySynReplyError(
2225 "407 Proxy Authentication Required",
2226 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2227 1));
2228 scoped_ptr<spdy::SpdyFrame> body_authentication(
2229 ConstructSpdyBodyFrame(1, true));
2230 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2231 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2232 MockRead spdy_reads[] = {
2233 CreateMockRead(*resp_authentication, 2),
2234 CreateMockRead(*body_authentication, 3),
2235 CreateMockRead(*resp_data, 5),
2236 CreateMockRead(*body_data, 6),
2237 MockRead(true, 0, 7),
2238 };
2239
[email protected]a1595312012-01-22 03:25:042240 scoped_ptr<OrderedSocketData> data(
[email protected]dc7bd1c52010-11-12 00:01:132241 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2242 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042243 session_deps.socket_factory.AddSocketDataProvider(data.get());
[email protected]dc7bd1c52010-11-12 00:01:132244
2245 SSLSocketDataProvider ssl(true, OK);
2246 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202247 ssl.next_proto = "spdy/2.1";
[email protected]dc7bd1c52010-11-12 00:01:132248 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202249 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]dc7bd1c52010-11-12 00:01:132250 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2251
[email protected]49639fa2011-12-20 23:22:412252 TestCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:132253
2254 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2255
[email protected]49639fa2011-12-20 23:22:412256 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]dc7bd1c52010-11-12 00:01:132257 EXPECT_EQ(ERR_IO_PENDING, rv);
2258
2259 rv = callback1.WaitForResult();
2260 EXPECT_EQ(OK, rv);
2261
2262 const HttpResponseInfo* const response = trans->GetResponseInfo();
2263
2264 ASSERT_TRUE(response != NULL);
2265 ASSERT_TRUE(response->headers != NULL);
2266 EXPECT_EQ(407, response->headers->response_code());
2267 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:042268 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:132269
[email protected]49639fa2011-12-20 23:22:412270 TestCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:132271
[email protected]49639fa2011-12-20 23:22:412272 rv = trans->RestartWithAuth(
2273 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]dc7bd1c52010-11-12 00:01:132274 EXPECT_EQ(ERR_IO_PENDING, rv);
2275
2276 rv = callback2.WaitForResult();
2277 EXPECT_EQ(OK, rv);
2278
2279 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2280
2281 ASSERT_TRUE(response_restart != NULL);
2282 ASSERT_TRUE(response_restart->headers != NULL);
2283 EXPECT_EQ(200, response_restart->headers->response_code());
2284 // The password prompt info should not be set.
2285 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2286}
2287
[email protected]d9da5fe2010-10-13 22:37:162288// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2289TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272290 HttpRequestInfo request;
2291 request.method = "GET";
2292 request.url = GURL("https://www.google.com/");
2293 request.load_flags = 0;
2294
[email protected]d9da5fe2010-10-13 22:37:162295 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112296 SessionDependencies session_deps(ProxyService::CreateFixed(
2297 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162298 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2299 session_deps.net_log = log.bound().net_log();
2300 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2301
2302 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2303
[email protected]d9da5fe2010-10-13 22:37:162304 // CONNECT to www.google.com:443 via SPDY
2305 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2306 // fetch https://www.google.com/ via HTTP
2307
2308 const char get[] = "GET / HTTP/1.1\r\n"
2309 "Host: www.google.com\r\n"
2310 "Connection: keep-alive\r\n\r\n";
2311 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2312 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2313 MockWrite spdy_writes[] = {
2314 CreateMockWrite(*connect, 1),
2315 CreateMockWrite(*wrapped_get, 3)
2316 };
2317
2318 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2319 const char resp[] = "HTTP/1.1 200 OK\r\n"
2320 "Content-Length: 10\r\n\r\n";
2321
2322 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2323 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2324 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2325 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2326 MockRead spdy_reads[] = {
2327 CreateMockRead(*conn_resp, 2, true),
2328 CreateMockRead(*wrapped_get_resp, 4, true),
2329 CreateMockRead(*wrapped_body, 5, true),
2330 CreateMockRead(*wrapped_body, 6, true),
2331 MockRead(true, 0, 7),
2332 };
2333
[email protected]a1595312012-01-22 03:25:042334 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162335 new OrderedSocketData(
2336 spdy_reads, arraysize(spdy_reads),
2337 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042338 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162339
2340 SSLSocketDataProvider ssl(true, OK);
2341 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202342 ssl.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162343 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202344 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162345 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2346 SSLSocketDataProvider ssl2(true, OK);
2347 ssl2.was_npn_negotiated = false;
[email protected]c30bcce2011-12-20 17:50:512348 ssl2.protocol_negotiated = SSLClientSocket::kProtoUnknown;
[email protected]d9da5fe2010-10-13 22:37:162349 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2350
[email protected]49639fa2011-12-20 23:22:412351 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162352
[email protected]49639fa2011-12-20 23:22:412353 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162354 EXPECT_EQ(ERR_IO_PENDING, rv);
2355
2356 rv = callback1.WaitForResult();
2357 EXPECT_EQ(OK, rv);
2358
2359 const HttpResponseInfo* response = trans->GetResponseInfo();
2360 ASSERT_TRUE(response != NULL);
2361 ASSERT_TRUE(response->headers != NULL);
2362 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2363
2364 std::string response_data;
2365 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2366 EXPECT_EQ("1234567890", response_data);
2367}
2368
2369// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2370TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272371 HttpRequestInfo request;
2372 request.method = "GET";
2373 request.url = GURL("https://www.google.com/");
2374 request.load_flags = 0;
2375
[email protected]d9da5fe2010-10-13 22:37:162376 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112377 SessionDependencies session_deps(ProxyService::CreateFixed(
2378 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162379 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2380 session_deps.net_log = log.bound().net_log();
2381 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2382
2383 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2384
[email protected]d9da5fe2010-10-13 22:37:162385 // CONNECT to www.google.com:443 via SPDY
2386 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2387 // fetch https://www.google.com/ via SPDY
2388 const char* const kMyUrl = "https://www.google.com/";
2389 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2390 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2391 MockWrite spdy_writes[] = {
2392 CreateMockWrite(*connect, 1),
2393 CreateMockWrite(*wrapped_get, 3)
2394 };
2395
2396 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2397 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2398 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2399 ConstructWrappedSpdyFrame(get_resp, 1));
2400 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2401 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2402 MockRead spdy_reads[] = {
2403 CreateMockRead(*conn_resp, 2, true),
2404 CreateMockRead(*wrapped_get_resp, 4, true),
2405 CreateMockRead(*wrapped_body, 5, true),
2406 MockRead(true, 0, 1),
2407 };
2408
[email protected]a1595312012-01-22 03:25:042409 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162410 new OrderedSocketData(
2411 spdy_reads, arraysize(spdy_reads),
2412 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042413 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162414
2415 SSLSocketDataProvider ssl(true, OK);
2416 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202417 ssl.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162418 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202419 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162420 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2421 SSLSocketDataProvider ssl2(true, OK);
2422 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202423 ssl2.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162424 ssl2.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202425 ssl2.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162426 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2427
[email protected]49639fa2011-12-20 23:22:412428 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162429
[email protected]49639fa2011-12-20 23:22:412430 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162431 EXPECT_EQ(ERR_IO_PENDING, rv);
2432
2433 rv = callback1.WaitForResult();
2434 EXPECT_EQ(OK, rv);
2435
2436 const HttpResponseInfo* response = trans->GetResponseInfo();
2437 ASSERT_TRUE(response != NULL);
2438 ASSERT_TRUE(response->headers != NULL);
2439 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2440
2441 std::string response_data;
2442 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2443 EXPECT_EQ(net::kUploadData, response_data);
2444}
2445
2446// Test a SPDY CONNECT failure through an HTTPS Proxy.
2447TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272448 HttpRequestInfo request;
2449 request.method = "GET";
2450 request.url = GURL("https://www.google.com/");
2451 request.load_flags = 0;
2452
[email protected]d9da5fe2010-10-13 22:37:162453 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112454 SessionDependencies session_deps(ProxyService::CreateFixed(
2455 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162456 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2457 session_deps.net_log = log.bound().net_log();
2458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2459
2460 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2461
[email protected]d9da5fe2010-10-13 22:37:162462 // CONNECT to www.google.com:443 via SPDY
2463 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2464 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2465
2466 MockWrite spdy_writes[] = {
2467 CreateMockWrite(*connect, 1),
2468 CreateMockWrite(*get, 3),
2469 };
2470
2471 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2472 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2473 MockRead spdy_reads[] = {
2474 CreateMockRead(*resp, 2, true),
2475 MockRead(true, 0, 4),
2476 };
2477
[email protected]a1595312012-01-22 03:25:042478 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d9da5fe2010-10-13 22:37:162479 new OrderedSocketData(
2480 spdy_reads, arraysize(spdy_reads),
2481 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:042482 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]d9da5fe2010-10-13 22:37:162483
2484 SSLSocketDataProvider ssl(true, OK);
2485 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202486 ssl.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162487 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202488 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162489 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2490 SSLSocketDataProvider ssl2(true, OK);
2491 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:202492 ssl2.next_proto = "spdy/2.1";
[email protected]d9da5fe2010-10-13 22:37:162493 ssl2.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:202494 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]d9da5fe2010-10-13 22:37:162495 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2496
[email protected]49639fa2011-12-20 23:22:412497 TestCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162498
[email protected]49639fa2011-12-20 23:22:412499 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]d9da5fe2010-10-13 22:37:162500 EXPECT_EQ(ERR_IO_PENDING, rv);
2501
2502 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292503 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162504
2505 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502506 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:292507 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162508}
2509
[email protected]2df19bb2010-08-25 20:13:462510// Test the challenge-response-retry sequence through an HTTPS Proxy
2511TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462512 HttpRequestInfo request;
2513 request.method = "GET";
2514 request.url = GURL("http://www.google.com/");
2515 // when the no authentication data flag is set.
2516 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2517
[email protected]79cb5c12011-09-12 13:12:042518 // Configure against https proxy server "myproxy:70".
2519 SessionDependencies session_deps(
2520 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]cb9bf6ca2011-01-28 13:15:272521 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2522 session_deps.net_log = log.bound().net_log();
2523 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2524
[email protected]2df19bb2010-08-25 20:13:462525 // Since we have proxy, should use full url
2526 MockWrite data_writes1[] = {
2527 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2528 "Host: www.google.com\r\n"
2529 "Proxy-Connection: keep-alive\r\n\r\n"),
2530
2531 // After calling trans->RestartWithAuth(), this is the request we should
2532 // be issuing -- the final header line contains the credentials.
2533 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2534 "Host: www.google.com\r\n"
2535 "Proxy-Connection: keep-alive\r\n"
2536 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2537 };
2538
2539 // The proxy responds to the GET with a 407, using a persistent
2540 // connection.
2541 MockRead data_reads1[] = {
2542 // No credentials.
2543 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2544 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2545 MockRead("Proxy-Connection: keep-alive\r\n"),
2546 MockRead("Content-Length: 0\r\n\r\n"),
2547
2548 MockRead("HTTP/1.1 200 OK\r\n"),
2549 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2550 MockRead("Content-Length: 100\r\n\r\n"),
2551 MockRead(false, OK),
2552 };
2553
2554 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2555 data_writes1, arraysize(data_writes1));
2556 session_deps.socket_factory.AddSocketDataProvider(&data1);
2557 SSLSocketDataProvider ssl(true, OK);
2558 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2559
[email protected]49639fa2011-12-20 23:22:412560 TestCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462561
[email protected]0b0bf032010-09-21 18:08:502562 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2563
[email protected]49639fa2011-12-20 23:22:412564 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]2df19bb2010-08-25 20:13:462565 EXPECT_EQ(ERR_IO_PENDING, rv);
2566
2567 rv = callback1.WaitForResult();
2568 EXPECT_EQ(OK, rv);
2569
2570 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502571 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042572 ASSERT_FALSE(response->headers == NULL);
[email protected]2df19bb2010-08-25 20:13:462573 EXPECT_EQ(407, response->headers->response_code());
2574 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042575 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:462576
[email protected]49639fa2011-12-20 23:22:412577 TestCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:462578
[email protected]49639fa2011-12-20 23:22:412579 rv = trans->RestartWithAuth(
2580 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]2df19bb2010-08-25 20:13:462581 EXPECT_EQ(ERR_IO_PENDING, rv);
2582
2583 rv = callback2.WaitForResult();
2584 EXPECT_EQ(OK, rv);
2585
2586 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502587 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462588
2589 EXPECT_TRUE(response->headers->IsKeepAlive());
2590 EXPECT_EQ(200, response->headers->response_code());
2591 EXPECT_EQ(100, response->headers->GetContentLength());
2592 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2593
2594 // The password prompt info should not be set.
2595 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2596}
2597
[email protected]ff007e162009-05-23 09:13:152598void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082599 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422600 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082601 request.method = "GET";
2602 request.url = GURL("https://www.google.com/");
2603 request.load_flags = 0;
2604
[email protected]cb9bf6ca2011-01-28 13:15:272605 // Configure against proxy server "myproxy:70".
2606 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2607
2608 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2609
[email protected]c744cf22009-02-27 07:28:082610 // Since we have proxy, should try to establish tunnel.
2611 MockWrite data_writes[] = {
2612 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452613 "Host: www.google.com\r\n"
2614 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082615 };
2616
2617 MockRead data_reads[] = {
2618 status,
2619 MockRead("Content-Length: 10\r\n\r\n"),
2620 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422621 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082622 };
2623
[email protected]31a2bfe2010-02-09 08:03:392624 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2625 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592626 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082627
[email protected]49639fa2011-12-20 23:22:412628 TestCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:082629
[email protected]0b0bf032010-09-21 18:08:502630 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2631
[email protected]49639fa2011-12-20 23:22:412632 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422633 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082634
2635 rv = callback.WaitForResult();
2636 EXPECT_EQ(expected_status, rv);
2637}
2638
[email protected]ff007e162009-05-23 09:13:152639void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082640 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422641 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082642}
2643
2644TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2645 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2646}
2647
2648TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2649 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2650}
2651
2652TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2653 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2654}
2655
2656TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2657 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2658}
2659
2660TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2661 ConnectStatusHelper(
2662 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2663}
2664
2665TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2666 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2667}
2668
2669TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2670 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2671}
2672
2673TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2674 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2675}
2676
2677TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2678 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2679}
2680
2681TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2682 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2683}
2684
2685TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2686 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2687}
2688
2689TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2690 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2691}
2692
2693TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2694 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2695}
2696
2697TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2698 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2699}
2700
2701TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2702 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2703}
2704
2705TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2706 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2707}
2708
2709TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2710 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2711}
2712
2713TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2714 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2715}
2716
2717TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2718 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2719}
2720
2721TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2722 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2723}
2724
2725TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2726 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2727}
2728
2729TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2730 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2731}
2732
2733TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2734 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2735}
2736
2737TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2738 ConnectStatusHelperWithExpectedStatus(
2739 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542740 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082741}
2742
2743TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2744 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2745}
2746
2747TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2748 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2749}
2750
2751TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2752 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2753}
2754
2755TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2756 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2757}
2758
2759TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2760 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2761}
2762
2763TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2764 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2765}
2766
2767TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2768 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2769}
2770
2771TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2772 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2773}
2774
2775TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2776 ConnectStatusHelper(
2777 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2778}
2779
2780TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2781 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2782}
2783
2784TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2785 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2786}
2787
2788TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2789 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2790}
2791
2792TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2793 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2794}
2795
2796TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2797 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2798}
2799
2800TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2801 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2802}
2803
2804TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2805 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2806}
2807
[email protected]038e9a32008-10-08 22:40:162808// Test the flow when both the proxy server AND origin server require
2809// authentication. Again, this uses basic auth for both since that is
2810// the simplest to mock.
2811TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272812 HttpRequestInfo request;
2813 request.method = "GET";
2814 request.url = GURL("http://www.google.com/");
2815 request.load_flags = 0;
2816
[email protected]81cdfcd2010-10-16 00:49:002817 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012818
[email protected]038e9a32008-10-08 22:40:162819 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422820 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432821 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162822
[email protected]f9ee6b52008-11-08 06:46:232823 MockWrite data_writes1[] = {
2824 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2825 "Host: www.google.com\r\n"
2826 "Proxy-Connection: keep-alive\r\n\r\n"),
2827 };
2828
[email protected]038e9a32008-10-08 22:40:162829 MockRead data_reads1[] = {
2830 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2831 // Give a couple authenticate options (only the middle one is actually
2832 // supported).
[email protected]22927ad2009-09-21 19:56:192833 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162834 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2835 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2836 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2837 // Large content-length -- won't matter, as connection will be reset.
2838 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422839 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162840 };
2841
2842 // After calling trans->RestartWithAuth() the first time, this is the
2843 // request we should be issuing -- the final header line contains the
2844 // proxy's credentials.
2845 MockWrite data_writes2[] = {
2846 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2847 "Host: www.google.com\r\n"
2848 "Proxy-Connection: keep-alive\r\n"
2849 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2850 };
2851
2852 // Now the proxy server lets the request pass through to origin server.
2853 // The origin server responds with a 401.
2854 MockRead data_reads2[] = {
2855 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2856 // Note: We are using the same realm-name as the proxy server. This is
2857 // completely valid, as realms are unique across hosts.
2858 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2859 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2860 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422861 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162862 };
2863
2864 // After calling trans->RestartWithAuth() the second time, we should send
2865 // the credentials for both the proxy and origin server.
2866 MockWrite data_writes3[] = {
2867 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2868 "Host: www.google.com\r\n"
2869 "Proxy-Connection: keep-alive\r\n"
2870 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2871 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2872 };
2873
2874 // Lastly we get the desired content.
2875 MockRead data_reads3[] = {
2876 MockRead("HTTP/1.0 200 OK\r\n"),
2877 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2878 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422879 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162880 };
2881
[email protected]31a2bfe2010-02-09 08:03:392882 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2883 data_writes1, arraysize(data_writes1));
2884 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2885 data_writes2, arraysize(data_writes2));
2886 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2887 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592888 session_deps.socket_factory.AddSocketDataProvider(&data1);
2889 session_deps.socket_factory.AddSocketDataProvider(&data2);
2890 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162891
[email protected]49639fa2011-12-20 23:22:412892 TestCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162893
[email protected]49639fa2011-12-20 23:22:412894 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422895 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162896
2897 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422898 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162899
[email protected]1c773ea12009-04-28 19:58:422900 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502901 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042902 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162903
[email protected]49639fa2011-12-20 23:22:412904 TestCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162905
[email protected]49639fa2011-12-20 23:22:412906 rv = trans->RestartWithAuth(
2907 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:422908 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162909
2910 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422911 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162912
2913 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502914 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042915 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162916
[email protected]49639fa2011-12-20 23:22:412917 TestCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:162918
[email protected]49639fa2011-12-20 23:22:412919 rv = trans->RestartWithAuth(
2920 AuthCredentials(kFoo2, kBar2), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:422921 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162922
2923 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422924 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162925
2926 response = trans->GetResponseInfo();
2927 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2928 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162929}
[email protected]4ddaf2502008-10-23 18:26:192930
[email protected]ea9dc9a2009-09-05 00:43:322931// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2932// can't hook into its internals to cause it to generate predictable NTLM
2933// authorization headers.
2934#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292935// The NTLM authentication unit tests were generated by capturing the HTTP
2936// requests and responses using Fiddler 2 and inspecting the generated random
2937// bytes in the debugger.
2938
2939// Enter the correct password and authenticate successfully.
2940TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422941 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242942 request.method = "GET";
2943 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2944 request.load_flags = 0;
2945
[email protected]cb9bf6ca2011-01-28 13:15:272946 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2947 MockGetHostName);
2948 SessionDependencies session_deps;
2949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2950
[email protected]3f918782009-02-28 01:29:242951 MockWrite data_writes1[] = {
2952 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2953 "Host: 172.22.68.17\r\n"
2954 "Connection: keep-alive\r\n\r\n"),
2955 };
2956
2957 MockRead data_reads1[] = {
2958 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042959 // Negotiate and NTLM are often requested together. However, we only want
2960 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2961 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242962 MockRead("WWW-Authenticate: NTLM\r\n"),
2963 MockRead("Connection: close\r\n"),
2964 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362965 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242966 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422967 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242968 };
2969
2970 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222971 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242972 // request we should be issuing -- the final header line contains a Type
2973 // 1 message.
2974 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2975 "Host: 172.22.68.17\r\n"
2976 "Connection: keep-alive\r\n"
2977 "Authorization: NTLM "
2978 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2979
2980 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2981 // (the credentials for the origin server). The second request continues
2982 // on the same connection.
2983 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2984 "Host: 172.22.68.17\r\n"
2985 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292986 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2987 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2988 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2989 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2990 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242991 };
2992
2993 MockRead data_reads2[] = {
2994 // The origin server responds with a Type 2 message.
2995 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2996 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292997 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242998 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2999 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3000 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3001 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3002 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3003 "BtAAAAAAA=\r\n"),
3004 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363005 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:243006 MockRead("You are not authorized to view this page\r\n"),
3007
3008 // Lastly we get the desired content.
3009 MockRead("HTTP/1.1 200 OK\r\n"),
3010 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3011 MockRead("Content-Length: 13\r\n\r\n"),
3012 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423013 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:243014 };
3015
[email protected]31a2bfe2010-02-09 08:03:393016 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3017 data_writes1, arraysize(data_writes1));
3018 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3019 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593020 session_deps.socket_factory.AddSocketDataProvider(&data1);
3021 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:243022
[email protected]49639fa2011-12-20 23:22:413023 TestCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:243024
[email protected]0b0bf032010-09-21 18:08:503025 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3026
[email protected]49639fa2011-12-20 23:22:413027 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423028 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243029
3030 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423031 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243032
[email protected]0757e7702009-03-27 04:00:223033 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3034
[email protected]1c773ea12009-04-28 19:58:423035 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043036 ASSERT_FALSE(response == NULL);
3037 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:243038
[email protected]49639fa2011-12-20 23:22:413039 TestCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:253040
[email protected]f3cf9802011-10-28 18:44:583041 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413042 callback2.callback());
[email protected]10af5fe72011-01-31 16:17:253043 EXPECT_EQ(ERR_IO_PENDING, rv);
3044
3045 rv = callback2.WaitForResult();
3046 EXPECT_EQ(OK, rv);
3047
3048 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3049
3050 response = trans->GetResponseInfo();
3051 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:253052 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3053
[email protected]49639fa2011-12-20 23:22:413054 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:243055
[email protected]49639fa2011-12-20 23:22:413056 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423057 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:243058
[email protected]0757e7702009-03-27 04:00:223059 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423060 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243061
3062 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503063 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:243064 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3065 EXPECT_EQ(13, response->headers->GetContentLength());
3066}
3067
[email protected]385a4672009-03-11 22:21:293068// Enter a wrong password, and then the correct one.
3069TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:423070 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:293071 request.method = "GET";
3072 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3073 request.load_flags = 0;
3074
[email protected]cb9bf6ca2011-01-28 13:15:273075 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3076 MockGetHostName);
3077 SessionDependencies session_deps;
3078 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3079
[email protected]385a4672009-03-11 22:21:293080 MockWrite data_writes1[] = {
3081 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3082 "Host: 172.22.68.17\r\n"
3083 "Connection: keep-alive\r\n\r\n"),
3084 };
3085
3086 MockRead data_reads1[] = {
3087 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:043088 // Negotiate and NTLM are often requested together. However, we only want
3089 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3090 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:293091 MockRead("WWW-Authenticate: NTLM\r\n"),
3092 MockRead("Connection: close\r\n"),
3093 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363094 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293095 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423096 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293097 };
3098
3099 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:223100 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293101 // request we should be issuing -- the final header line contains a Type
3102 // 1 message.
3103 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3104 "Host: 172.22.68.17\r\n"
3105 "Connection: keep-alive\r\n"
3106 "Authorization: NTLM "
3107 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3108
3109 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3110 // (the credentials for the origin server). The second request continues
3111 // on the same connection.
3112 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3113 "Host: 172.22.68.17\r\n"
3114 "Connection: keep-alive\r\n"
3115 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3116 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3117 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
3118 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
3119 "4Ww7b7E=\r\n\r\n"),
3120 };
3121
3122 MockRead data_reads2[] = {
3123 // The origin server responds with a Type 2 message.
3124 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3125 MockRead("WWW-Authenticate: NTLM "
3126 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
3127 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3128 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3129 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3130 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3131 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3132 "BtAAAAAAA=\r\n"),
3133 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363134 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293135 MockRead("You are not authorized to view this page\r\n"),
3136
3137 // Wrong password.
3138 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:293139 MockRead("WWW-Authenticate: NTLM\r\n"),
3140 MockRead("Connection: close\r\n"),
3141 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363142 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293143 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423144 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293145 };
3146
3147 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223148 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293149 // request we should be issuing -- the final header line contains a Type
3150 // 1 message.
3151 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3152 "Host: 172.22.68.17\r\n"
3153 "Connection: keep-alive\r\n"
3154 "Authorization: NTLM "
3155 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3156
3157 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3158 // (the credentials for the origin server). The second request continues
3159 // on the same connection.
3160 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3161 "Host: 172.22.68.17\r\n"
3162 "Connection: keep-alive\r\n"
3163 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3164 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3165 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3166 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3167 "+4MUm7c=\r\n\r\n"),
3168 };
3169
3170 MockRead data_reads3[] = {
3171 // The origin server responds with a Type 2 message.
3172 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3173 MockRead("WWW-Authenticate: NTLM "
3174 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3175 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3176 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3177 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3178 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3179 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3180 "BtAAAAAAA=\r\n"),
3181 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363182 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293183 MockRead("You are not authorized to view this page\r\n"),
3184
3185 // Lastly we get the desired content.
3186 MockRead("HTTP/1.1 200 OK\r\n"),
3187 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3188 MockRead("Content-Length: 13\r\n\r\n"),
3189 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423190 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293191 };
3192
[email protected]31a2bfe2010-02-09 08:03:393193 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3194 data_writes1, arraysize(data_writes1));
3195 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3196 data_writes2, arraysize(data_writes2));
3197 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3198 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593199 session_deps.socket_factory.AddSocketDataProvider(&data1);
3200 session_deps.socket_factory.AddSocketDataProvider(&data2);
3201 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293202
[email protected]49639fa2011-12-20 23:22:413203 TestCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:293204
[email protected]0b0bf032010-09-21 18:08:503205 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3206
[email protected]49639fa2011-12-20 23:22:413207 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423208 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293209
3210 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423211 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293212
[email protected]0757e7702009-03-27 04:00:223213 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293214
[email protected]1c773ea12009-04-28 19:58:423215 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503216 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043217 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:293218
[email protected]49639fa2011-12-20 23:22:413219 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293220
[email protected]0757e7702009-03-27 04:00:223221 // Enter the wrong password.
[email protected]f3cf9802011-10-28 18:44:583222 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kWrongPassword),
[email protected]49639fa2011-12-20 23:22:413223 callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423224 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293225
[email protected]10af5fe72011-01-31 16:17:253226 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423227 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293228
[email protected]0757e7702009-03-27 04:00:223229 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:413230 TestCompletionCallback callback3;
3231 rv = trans->RestartWithAuth(AuthCredentials(), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:423232 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253233 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423234 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223235 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3236
3237 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043238 ASSERT_FALSE(response == NULL);
3239 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:223240
[email protected]49639fa2011-12-20 23:22:413241 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223242
3243 // Now enter the right password.
[email protected]f3cf9802011-10-28 18:44:583244 rv = trans->RestartWithAuth(AuthCredentials(kTestingNTLM, kTestingNTLM),
[email protected]49639fa2011-12-20 23:22:413245 callback4.callback());
[email protected]10af5fe72011-01-31 16:17:253246 EXPECT_EQ(ERR_IO_PENDING, rv);
3247
3248 rv = callback4.WaitForResult();
3249 EXPECT_EQ(OK, rv);
3250
3251 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3252
[email protected]49639fa2011-12-20 23:22:413253 TestCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:253254
3255 // One more roundtrip
[email protected]49639fa2011-12-20 23:22:413256 rv = trans->RestartWithAuth(AuthCredentials(), callback5.callback());
[email protected]1c773ea12009-04-28 19:58:423257 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223258
3259 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423260 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223261
[email protected]385a4672009-03-11 22:21:293262 response = trans->GetResponseInfo();
3263 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3264 EXPECT_EQ(13, response->headers->GetContentLength());
3265}
[email protected]ea9dc9a2009-09-05 00:43:323266#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293267
[email protected]4ddaf2502008-10-23 18:26:193268// Test reading a server response which has only headers, and no body.
3269// After some maximum number of bytes is consumed, the transaction should
3270// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3271TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423272 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193273 request.method = "GET";
3274 request.url = GURL("http://www.google.com/");
3275 request.load_flags = 0;
3276
[email protected]cb9bf6ca2011-01-28 13:15:273277 SessionDependencies session_deps;
3278 scoped_ptr<HttpTransaction> trans(
3279 new HttpNetworkTransaction(CreateSession(&session_deps)));
3280
[email protected]b75b7b2f2009-10-06 00:54:533281 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433282 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533283 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193284
3285 MockRead data_reads[] = {
3286 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433287 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193288 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423289 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193290 };
[email protected]31a2bfe2010-02-09 08:03:393291 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593292 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193293
[email protected]49639fa2011-12-20 23:22:413294 TestCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:193295
[email protected]49639fa2011-12-20 23:22:413296 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423297 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193298
3299 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423300 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193301
[email protected]1c773ea12009-04-28 19:58:423302 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193303 EXPECT_TRUE(response == NULL);
3304}
[email protected]f4e426b2008-11-05 00:24:493305
3306// Make sure that we don't try to reuse a TCPClientSocket when failing to
3307// establish tunnel.
3308// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283309TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273310 HttpRequestInfo request;
3311 request.method = "GET";
3312 request.url = GURL("https://www.google.com/");
3313 request.load_flags = 0;
3314
[email protected]f4e426b2008-11-05 00:24:493315 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003316 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013317
[email protected]228ff742009-06-05 01:19:593318 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493319
[email protected]5695b8c2009-09-30 21:36:433320 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493321
[email protected]f4e426b2008-11-05 00:24:493322 // Since we have proxy, should try to establish tunnel.
3323 MockWrite data_writes1[] = {
3324 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453325 "Host: www.google.com\r\n"
3326 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493327 };
3328
[email protected]77848d12008-11-14 00:00:223329 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493330 // connection. Usually a proxy would return 501 (not implemented),
3331 // or 200 (tunnel established).
3332 MockRead data_reads1[] = {
3333 MockRead("HTTP/1.1 404 Not Found\r\n"),
3334 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423335 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493336 };
3337
[email protected]31a2bfe2010-02-09 08:03:393338 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3339 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593340 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493341
[email protected]49639fa2011-12-20 23:22:413342 TestCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:493343
[email protected]49639fa2011-12-20 23:22:413344 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423345 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493346
3347 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423348 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493349
[email protected]1c773ea12009-04-28 19:58:423350 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083351 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493352
[email protected]b4404c02009-04-10 16:38:523353 // Empty the current queue. This is necessary because idle sockets are
3354 // added to the connection pool asynchronously with a PostTask.
3355 MessageLoop::current()->RunAllPending();
3356
[email protected]f4e426b2008-11-05 00:24:493357 // We now check to make sure the TCPClientSocket was not added back to
3358 // the pool.
[email protected]a42dbd142011-11-17 16:42:023359 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493360 trans.reset();
[email protected]b4404c02009-04-10 16:38:523361 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493362 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]a42dbd142011-11-17 16:42:023363 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493364}
[email protected]372d34a2008-11-05 21:30:513365
[email protected]1b157c02009-04-21 01:55:403366// Make sure that we recycle a socket after reading all of the response body.
3367TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423368 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403369 request.method = "GET";
3370 request.url = GURL("http://www.google.com/");
3371 request.load_flags = 0;
3372
[email protected]cb9bf6ca2011-01-28 13:15:273373 SessionDependencies session_deps;
3374 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3375
3376 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3377
[email protected]1b157c02009-04-21 01:55:403378 MockRead data_reads[] = {
3379 // A part of the response body is received with the response headers.
3380 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3381 // The rest of the response body is received in two parts.
3382 MockRead("lo"),
3383 MockRead(" world"),
3384 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423385 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403386 };
3387
[email protected]31a2bfe2010-02-09 08:03:393388 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593389 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403390
[email protected]49639fa2011-12-20 23:22:413391 TestCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:403392
[email protected]49639fa2011-12-20 23:22:413393 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423394 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403395
3396 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423397 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403398
[email protected]1c773ea12009-04-28 19:58:423399 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503400 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:403401
3402 EXPECT_TRUE(response->headers != NULL);
3403 std::string status_line = response->headers->GetStatusLine();
3404 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3405
[email protected]a42dbd142011-11-17 16:42:023406 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403407
3408 std::string response_data;
3409 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423410 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403411 EXPECT_EQ("hello world", response_data);
3412
3413 // Empty the current queue. This is necessary because idle sockets are
3414 // added to the connection pool asynchronously with a PostTask.
3415 MessageLoop::current()->RunAllPending();
3416
3417 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023418 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403419}
3420
[email protected]76a505b2010-08-25 06:23:003421// Make sure that we recycle a SSL socket after reading all of the response
3422// body.
3423TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3424 SessionDependencies session_deps;
3425 HttpRequestInfo request;
3426 request.method = "GET";
3427 request.url = GURL("https://www.google.com/");
3428 request.load_flags = 0;
3429
3430 MockWrite data_writes[] = {
3431 MockWrite("GET / HTTP/1.1\r\n"
3432 "Host: www.google.com\r\n"
3433 "Connection: keep-alive\r\n\r\n"),
3434 };
3435
3436 MockRead data_reads[] = {
3437 MockRead("HTTP/1.1 200 OK\r\n"),
3438 MockRead("Content-Length: 11\r\n\r\n"),
3439 MockRead("hello world"),
3440 MockRead(false, OK),
3441 };
3442
3443 SSLSocketDataProvider ssl(true, OK);
3444 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3445
3446 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3447 data_writes, arraysize(data_writes));
3448 session_deps.socket_factory.AddSocketDataProvider(&data);
3449
[email protected]49639fa2011-12-20 23:22:413450 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003451
3452 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3453 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3454
[email protected]49639fa2011-12-20 23:22:413455 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003456
3457 EXPECT_EQ(ERR_IO_PENDING, rv);
3458 EXPECT_EQ(OK, callback.WaitForResult());
3459
3460 const HttpResponseInfo* response = trans->GetResponseInfo();
3461 ASSERT_TRUE(response != NULL);
3462 ASSERT_TRUE(response->headers != NULL);
3463 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3464
[email protected]a42dbd142011-11-17 16:42:023465 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003466
3467 std::string response_data;
3468 rv = ReadTransaction(trans.get(), &response_data);
3469 EXPECT_EQ(OK, rv);
3470 EXPECT_EQ("hello world", response_data);
3471
3472 // Empty the current queue. This is necessary because idle sockets are
3473 // added to the connection pool asynchronously with a PostTask.
3474 MessageLoop::current()->RunAllPending();
3475
3476 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023477 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003478}
3479
3480// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3481// from the pool and make sure that we recover okay.
3482TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3483 SessionDependencies session_deps;
3484 HttpRequestInfo request;
3485 request.method = "GET";
3486 request.url = GURL("https://www.google.com/");
3487 request.load_flags = 0;
3488
3489 MockWrite data_writes[] = {
3490 MockWrite("GET / HTTP/1.1\r\n"
3491 "Host: www.google.com\r\n"
3492 "Connection: keep-alive\r\n\r\n"),
3493 MockWrite("GET / HTTP/1.1\r\n"
3494 "Host: www.google.com\r\n"
3495 "Connection: keep-alive\r\n\r\n"),
3496 };
3497
3498 MockRead data_reads[] = {
3499 MockRead("HTTP/1.1 200 OK\r\n"),
3500 MockRead("Content-Length: 11\r\n\r\n"),
3501 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3502 MockRead("hello world"),
3503 MockRead(true, 0, 0) // EOF
3504 };
3505
3506 SSLSocketDataProvider ssl(true, OK);
3507 SSLSocketDataProvider ssl2(true, OK);
3508 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3509 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3510
3511 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3512 data_writes, arraysize(data_writes));
3513 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3514 data_writes, arraysize(data_writes));
3515 session_deps.socket_factory.AddSocketDataProvider(&data);
3516 session_deps.socket_factory.AddSocketDataProvider(&data2);
3517
[email protected]49639fa2011-12-20 23:22:413518 TestCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003519
3520 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3521 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3522
[email protected]49639fa2011-12-20 23:22:413523 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003524
3525 EXPECT_EQ(ERR_IO_PENDING, rv);
3526 EXPECT_EQ(OK, callback.WaitForResult());
3527
3528 const HttpResponseInfo* response = trans->GetResponseInfo();
3529 ASSERT_TRUE(response != NULL);
3530 ASSERT_TRUE(response->headers != NULL);
3531 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3532
[email protected]a42dbd142011-11-17 16:42:023533 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003534
3535 std::string response_data;
3536 rv = ReadTransaction(trans.get(), &response_data);
3537 EXPECT_EQ(OK, rv);
3538 EXPECT_EQ("hello world", response_data);
3539
3540 // Empty the current queue. This is necessary because idle sockets are
3541 // added to the connection pool asynchronously with a PostTask.
3542 MessageLoop::current()->RunAllPending();
3543
3544 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023545 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003546
3547 // Now start the second transaction, which should reuse the previous socket.
3548
3549 trans.reset(new HttpNetworkTransaction(session));
3550
[email protected]49639fa2011-12-20 23:22:413551 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]76a505b2010-08-25 06:23:003552
3553 EXPECT_EQ(ERR_IO_PENDING, rv);
3554 EXPECT_EQ(OK, callback.WaitForResult());
3555
3556 response = trans->GetResponseInfo();
3557 ASSERT_TRUE(response != NULL);
3558 ASSERT_TRUE(response->headers != NULL);
3559 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3560
[email protected]a42dbd142011-11-17 16:42:023561 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003562
3563 rv = ReadTransaction(trans.get(), &response_data);
3564 EXPECT_EQ(OK, rv);
3565 EXPECT_EQ("hello world", response_data);
3566
3567 // Empty the current queue. This is necessary because idle sockets are
3568 // added to the connection pool asynchronously with a PostTask.
3569 MessageLoop::current()->RunAllPending();
3570
3571 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023572 EXPECT_EQ(1, session->GetSSLSocketPool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003573}
3574
[email protected]b4404c02009-04-10 16:38:523575// Make sure that we recycle a socket after a zero-length response.
3576// http://crbug.com/9880
3577TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423578 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523579 request.method = "GET";
3580 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3581 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3582 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3583 "rt=prt.2642,ol.2649,xjs.2951");
3584 request.load_flags = 0;
3585
[email protected]cb9bf6ca2011-01-28 13:15:273586 SessionDependencies session_deps;
3587 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3588
3589 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3590
[email protected]b4404c02009-04-10 16:38:523591 MockRead data_reads[] = {
3592 MockRead("HTTP/1.1 204 No Content\r\n"
3593 "Content-Length: 0\r\n"
3594 "Content-Type: text/html\r\n\r\n"),
3595 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423596 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523597 };
3598
[email protected]31a2bfe2010-02-09 08:03:393599 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593600 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523601
[email protected]49639fa2011-12-20 23:22:413602 TestCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:523603
[email protected]49639fa2011-12-20 23:22:413604 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423605 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523606
3607 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423608 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523609
[email protected]1c773ea12009-04-28 19:58:423610 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503611 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:523612
3613 EXPECT_TRUE(response->headers != NULL);
3614 std::string status_line = response->headers->GetStatusLine();
3615 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3616
[email protected]a42dbd142011-11-17 16:42:023617 EXPECT_EQ(0, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523618
3619 std::string response_data;
3620 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423621 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523622 EXPECT_EQ("", response_data);
3623
3624 // Empty the current queue. This is necessary because idle sockets are
3625 // added to the connection pool asynchronously with a PostTask.
3626 MessageLoop::current()->RunAllPending();
3627
3628 // We now check to make sure the socket was added back to the pool.
[email protected]a42dbd142011-11-17 16:42:023629 EXPECT_EQ(1, session->GetTransportSocketPool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523630}
3631
[email protected]372d34a2008-11-05 21:30:513632TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423633 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513634 // Transaction 1: a GET request that succeeds. The socket is recycled
3635 // after use.
3636 request[0].method = "GET";
3637 request[0].url = GURL("http://www.google.com/");
3638 request[0].load_flags = 0;
3639 // Transaction 2: a POST request. Reuses the socket kept alive from
3640 // transaction 1. The first attempts fails when writing the POST data.
3641 // This causes the transaction to retry with a new socket. The second
3642 // attempt succeeds.
3643 request[1].method = "POST";
3644 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423645 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513646 request[1].upload_data->AppendBytes("foo", 3);
3647 request[1].load_flags = 0;
3648
[email protected]228ff742009-06-05 01:19:593649 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273650 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513651
3652 // The first socket is used for transaction 1 and the first attempt of
3653 // transaction 2.
3654
3655 // The response of transaction 1.
3656 MockRead data_reads1[] = {
3657 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3658 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423659 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513660 };
3661 // The mock write results of transaction 1 and the first attempt of
3662 // transaction 2.
3663 MockWrite data_writes1[] = {
3664 MockWrite(false, 64), // GET
3665 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423666 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513667 };
[email protected]31a2bfe2010-02-09 08:03:393668 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3669 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513670
3671 // The second socket is used for the second attempt of transaction 2.
3672
3673 // The response of transaction 2.
3674 MockRead data_reads2[] = {
3675 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3676 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423677 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513678 };
3679 // The mock write results of the second attempt of transaction 2.
3680 MockWrite data_writes2[] = {
3681 MockWrite(false, 93), // POST
3682 MockWrite(false, 3), // POST data
3683 };
[email protected]31a2bfe2010-02-09 08:03:393684 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3685 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513686
[email protected]5ecc992a42009-11-11 01:41:593687 session_deps.socket_factory.AddSocketDataProvider(&data1);
3688 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513689
3690 const char* kExpectedResponseData[] = {
3691 "hello world", "welcome"
3692 };
3693
3694 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423695 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433696 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513697
[email protected]49639fa2011-12-20 23:22:413698 TestCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:513699
[email protected]49639fa2011-12-20 23:22:413700 int rv = trans->Start(&request[i], callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423701 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513702
3703 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423704 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513705
[email protected]1c773ea12009-04-28 19:58:423706 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503707 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:513708
3709 EXPECT_TRUE(response->headers != NULL);
3710 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3711
3712 std::string response_data;
3713 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423714 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513715 EXPECT_EQ(kExpectedResponseData[i], response_data);
3716 }
3717}
[email protected]f9ee6b52008-11-08 06:46:233718
3719// Test the request-challenge-retry sequence for basic auth when there is
3720// an identity in the URL. The request should be sent as normal, but when
3721// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323722TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423723 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233724 request.method = "GET";
3725 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293726 request.url = GURL("http://foo:b@[email protected]/");
3727
[email protected]cb9bf6ca2011-01-28 13:15:273728 SessionDependencies session_deps;
3729 scoped_ptr<HttpTransaction> trans(
3730 new HttpNetworkTransaction(CreateSession(&session_deps)));
3731
[email protected]a97cca42009-08-14 01:00:293732 // The password contains an escaped character -- for this test to pass it
3733 // will need to be unescaped by HttpNetworkTransaction.
3734 EXPECT_EQ("b%40r", request.url.password());
3735
[email protected]ea9dc9a2009-09-05 00:43:323736 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233737
3738 MockWrite data_writes1[] = {
3739 MockWrite("GET / HTTP/1.1\r\n"
3740 "Host: www.google.com\r\n"
3741 "Connection: keep-alive\r\n\r\n"),
3742 };
3743
3744 MockRead data_reads1[] = {
3745 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3746 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3747 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423748 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233749 };
3750
3751 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323752 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233753 MockWrite data_writes2[] = {
3754 MockWrite("GET / HTTP/1.1\r\n"
3755 "Host: www.google.com\r\n"
3756 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293757 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233758 };
3759
3760 MockRead data_reads2[] = {
3761 MockRead("HTTP/1.0 200 OK\r\n"),
3762 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423763 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233764 };
3765
[email protected]31a2bfe2010-02-09 08:03:393766 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3767 data_writes1, arraysize(data_writes1));
3768 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3769 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593770 session_deps.socket_factory.AddSocketDataProvider(&data1);
3771 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233772
[email protected]49639fa2011-12-20 23:22:413773 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233774
[email protected]49639fa2011-12-20 23:22:413775 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423776 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233777
3778 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423779 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233780
[email protected]0757e7702009-03-27 04:00:223781 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:413782 TestCompletionCallback callback2;
3783 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423784 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223785 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423786 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223787 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3788
[email protected]1c773ea12009-04-28 19:58:423789 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503790 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233791
3792 // There is no challenge info, since the identity in URL worked.
3793 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3794
3795 EXPECT_EQ(100, response->headers->GetContentLength());
3796
3797 // Empty the current queue.
3798 MessageLoop::current()->RunAllPending();
3799}
3800
[email protected]ea9dc9a2009-09-05 00:43:323801// Test the request-challenge-retry sequence for basic auth when there is
3802// an incorrect identity in the URL. The identity from the URL should be used
3803// only once.
3804TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323805 HttpRequestInfo request;
3806 request.method = "GET";
3807 // Note: the URL has a username:password in it. The password "baz" is
3808 // wrong (should be "bar").
3809 request.url = GURL("http://foo:[email protected]/");
3810
3811 request.load_flags = LOAD_NORMAL;
3812
[email protected]cb9bf6ca2011-01-28 13:15:273813 SessionDependencies session_deps;
3814 scoped_ptr<HttpTransaction> trans(
3815 new HttpNetworkTransaction(CreateSession(&session_deps)));
3816
[email protected]ea9dc9a2009-09-05 00:43:323817 MockWrite data_writes1[] = {
3818 MockWrite("GET / HTTP/1.1\r\n"
3819 "Host: www.google.com\r\n"
3820 "Connection: keep-alive\r\n\r\n"),
3821 };
3822
3823 MockRead data_reads1[] = {
3824 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3825 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3826 MockRead("Content-Length: 10\r\n\r\n"),
3827 MockRead(false, ERR_FAILED),
3828 };
3829
3830 // After the challenge above, the transaction will be restarted using the
3831 // identity from the url (foo, baz) to answer the challenge.
3832 MockWrite data_writes2[] = {
3833 MockWrite("GET / HTTP/1.1\r\n"
3834 "Host: www.google.com\r\n"
3835 "Connection: keep-alive\r\n"
3836 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3837 };
3838
3839 MockRead data_reads2[] = {
3840 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3841 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3842 MockRead("Content-Length: 10\r\n\r\n"),
3843 MockRead(false, ERR_FAILED),
3844 };
3845
3846 // After the challenge above, the transaction will be restarted using the
3847 // identity supplied by the user (foo, bar) to answer the challenge.
3848 MockWrite data_writes3[] = {
3849 MockWrite("GET / HTTP/1.1\r\n"
3850 "Host: www.google.com\r\n"
3851 "Connection: keep-alive\r\n"
3852 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3853 };
3854
3855 MockRead data_reads3[] = {
3856 MockRead("HTTP/1.0 200 OK\r\n"),
3857 MockRead("Content-Length: 100\r\n\r\n"),
3858 MockRead(false, OK),
3859 };
3860
[email protected]31a2bfe2010-02-09 08:03:393861 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3862 data_writes1, arraysize(data_writes1));
3863 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3864 data_writes2, arraysize(data_writes2));
3865 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3866 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593867 session_deps.socket_factory.AddSocketDataProvider(&data1);
3868 session_deps.socket_factory.AddSocketDataProvider(&data2);
3869 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323870
[email protected]49639fa2011-12-20 23:22:413871 TestCompletionCallback callback1;
[email protected]ea9dc9a2009-09-05 00:43:323872
[email protected]49639fa2011-12-20 23:22:413873 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323874 EXPECT_EQ(ERR_IO_PENDING, rv);
3875
3876 rv = callback1.WaitForResult();
3877 EXPECT_EQ(OK, rv);
3878
3879 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:413880 TestCompletionCallback callback2;
3881 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]ea9dc9a2009-09-05 00:43:323882 EXPECT_EQ(ERR_IO_PENDING, rv);
3883 rv = callback2.WaitForResult();
3884 EXPECT_EQ(OK, rv);
3885 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3886
3887 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503888 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043889 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]ea9dc9a2009-09-05 00:43:323890
[email protected]49639fa2011-12-20 23:22:413891 TestCompletionCallback callback3;
3892 rv = trans->RestartWithAuth(
3893 AuthCredentials(kFoo, kBar), callback3.callback());
[email protected]ea9dc9a2009-09-05 00:43:323894 EXPECT_EQ(ERR_IO_PENDING, rv);
3895 rv = callback3.WaitForResult();
3896 EXPECT_EQ(OK, rv);
3897 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3898
3899 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503900 ASSERT_TRUE(response != NULL);
[email protected]ea9dc9a2009-09-05 00:43:323901
3902 // There is no challenge info, since the identity worked.
3903 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3904
3905 EXPECT_EQ(100, response->headers->GetContentLength());
3906
3907 // Empty the current queue.
3908 MessageLoop::current()->RunAllPending();
3909}
3910
[email protected]f9ee6b52008-11-08 06:46:233911// Test that previously tried username/passwords for a realm get re-used.
3912TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593913 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273914 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233915
3916 // Transaction 1: authenticate (foo, bar) on MyRealm1
3917 {
[email protected]1c773ea12009-04-28 19:58:423918 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233919 request.method = "GET";
3920 request.url = GURL("http://www.google.com/x/y/z");
3921 request.load_flags = 0;
3922
[email protected]cb9bf6ca2011-01-28 13:15:273923 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3924
[email protected]f9ee6b52008-11-08 06:46:233925 MockWrite data_writes1[] = {
3926 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3927 "Host: www.google.com\r\n"
3928 "Connection: keep-alive\r\n\r\n"),
3929 };
3930
3931 MockRead data_reads1[] = {
3932 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3933 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3934 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423935 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233936 };
3937
3938 // Resend with authorization (username=foo, password=bar)
3939 MockWrite data_writes2[] = {
3940 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3941 "Host: www.google.com\r\n"
3942 "Connection: keep-alive\r\n"
3943 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3944 };
3945
3946 // Sever accepts the authorization.
3947 MockRead data_reads2[] = {
3948 MockRead("HTTP/1.0 200 OK\r\n"),
3949 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423950 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233951 };
3952
[email protected]31a2bfe2010-02-09 08:03:393953 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3954 data_writes1, arraysize(data_writes1));
3955 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3956 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593957 session_deps.socket_factory.AddSocketDataProvider(&data1);
3958 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233959
[email protected]49639fa2011-12-20 23:22:413960 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233961
[email protected]49639fa2011-12-20 23:22:413962 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423963 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233964
3965 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423966 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233967
[email protected]1c773ea12009-04-28 19:58:423968 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503969 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043970 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:233971
[email protected]49639fa2011-12-20 23:22:413972 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233973
[email protected]49639fa2011-12-20 23:22:413974 rv = trans->RestartWithAuth(
3975 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:423976 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233977
3978 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423979 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233980
3981 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503982 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233983 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3984 EXPECT_EQ(100, response->headers->GetContentLength());
3985 }
3986
3987 // ------------------------------------------------------------------------
3988
3989 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3990 {
[email protected]1c773ea12009-04-28 19:58:423991 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233992 request.method = "GET";
3993 // Note that Transaction 1 was at /x/y/z, so this is in the same
3994 // protection space as MyRealm1.
3995 request.url = GURL("http://www.google.com/x/y/a/b");
3996 request.load_flags = 0;
3997
[email protected]cb9bf6ca2011-01-28 13:15:273998 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3999
[email protected]f9ee6b52008-11-08 06:46:234000 MockWrite data_writes1[] = {
4001 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4002 "Host: www.google.com\r\n"
4003 "Connection: keep-alive\r\n"
4004 // Send preemptive authorization for MyRealm1
4005 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4006 };
4007
4008 // The server didn't like the preemptive authorization, and
4009 // challenges us for a different realm (MyRealm2).
4010 MockRead data_reads1[] = {
4011 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4012 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
4013 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424014 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234015 };
4016
4017 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
4018 MockWrite data_writes2[] = {
4019 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4020 "Host: www.google.com\r\n"
4021 "Connection: keep-alive\r\n"
4022 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
4023 };
4024
4025 // Sever accepts the authorization.
4026 MockRead data_reads2[] = {
4027 MockRead("HTTP/1.0 200 OK\r\n"),
4028 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424029 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234030 };
4031
[email protected]31a2bfe2010-02-09 08:03:394032 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4033 data_writes1, arraysize(data_writes1));
4034 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4035 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594036 session_deps.socket_factory.AddSocketDataProvider(&data1);
4037 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234038
[email protected]49639fa2011-12-20 23:22:414039 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234040
[email protected]49639fa2011-12-20 23:22:414041 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424042 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234043
4044 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424045 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234046
[email protected]1c773ea12009-04-28 19:58:424047 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504048 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044049 ASSERT_TRUE(response->auth_challenge.get());
4050 EXPECT_FALSE(response->auth_challenge->is_proxy);
4051 EXPECT_EQ("www.google.com:80",
4052 response->auth_challenge->challenger.ToString());
4053 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
4054 EXPECT_EQ("basic", response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:234055
[email protected]49639fa2011-12-20 23:22:414056 TestCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:234057
[email protected]49639fa2011-12-20 23:22:414058 rv = trans->RestartWithAuth(
4059 AuthCredentials(kFoo2, kBar2), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424060 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234061
4062 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424063 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234064
4065 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504066 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234067 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4068 EXPECT_EQ(100, response->headers->GetContentLength());
4069 }
4070
4071 // ------------------------------------------------------------------------
4072
4073 // Transaction 3: Resend a request in MyRealm's protection space --
4074 // succeed with preemptive authorization.
4075 {
[email protected]1c773ea12009-04-28 19:58:424076 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234077 request.method = "GET";
4078 request.url = GURL("http://www.google.com/x/y/z2");
4079 request.load_flags = 0;
4080
[email protected]cb9bf6ca2011-01-28 13:15:274081 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4082
[email protected]f9ee6b52008-11-08 06:46:234083 MockWrite data_writes1[] = {
4084 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
4085 "Host: www.google.com\r\n"
4086 "Connection: keep-alive\r\n"
4087 // The authorization for MyRealm1 gets sent preemptively
4088 // (since the url is in the same protection space)
4089 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4090 };
4091
4092 // Sever accepts the preemptive authorization
4093 MockRead data_reads1[] = {
4094 MockRead("HTTP/1.0 200 OK\r\n"),
4095 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424096 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234097 };
4098
[email protected]31a2bfe2010-02-09 08:03:394099 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4100 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594101 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:234102
[email protected]49639fa2011-12-20 23:22:414103 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234104
[email protected]49639fa2011-12-20 23:22:414105 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424106 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234107
4108 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424109 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234110
[email protected]1c773ea12009-04-28 19:58:424111 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504112 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234113
4114 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4115 EXPECT_EQ(100, response->headers->GetContentLength());
4116 }
4117
4118 // ------------------------------------------------------------------------
4119
4120 // Transaction 4: request another URL in MyRealm (however the
4121 // url is not known to belong to the protection space, so no pre-auth).
4122 {
[email protected]1c773ea12009-04-28 19:58:424123 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234124 request.method = "GET";
4125 request.url = GURL("http://www.google.com/x/1");
4126 request.load_flags = 0;
4127
[email protected]cb9bf6ca2011-01-28 13:15:274128 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4129
[email protected]f9ee6b52008-11-08 06:46:234130 MockWrite data_writes1[] = {
4131 MockWrite("GET /x/1 HTTP/1.1\r\n"
4132 "Host: www.google.com\r\n"
4133 "Connection: keep-alive\r\n\r\n"),
4134 };
4135
4136 MockRead data_reads1[] = {
4137 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4138 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4139 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424140 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234141 };
4142
4143 // Resend with authorization from MyRealm's cache.
4144 MockWrite data_writes2[] = {
4145 MockWrite("GET /x/1 HTTP/1.1\r\n"
4146 "Host: www.google.com\r\n"
4147 "Connection: keep-alive\r\n"
4148 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4149 };
4150
4151 // Sever accepts the authorization.
4152 MockRead data_reads2[] = {
4153 MockRead("HTTP/1.0 200 OK\r\n"),
4154 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424155 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234156 };
4157
[email protected]31a2bfe2010-02-09 08:03:394158 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4159 data_writes1, arraysize(data_writes1));
4160 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4161 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594162 session_deps.socket_factory.AddSocketDataProvider(&data1);
4163 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234164
[email protected]49639fa2011-12-20 23:22:414165 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234166
[email protected]49639fa2011-12-20 23:22:414167 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424168 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234169
4170 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424171 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234172
[email protected]0757e7702009-03-27 04:00:224173 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414174 TestCompletionCallback callback2;
4175 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424176 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224177 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424178 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224179 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4180
[email protected]1c773ea12009-04-28 19:58:424181 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504182 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234183 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4184 EXPECT_EQ(100, response->headers->GetContentLength());
4185 }
4186
4187 // ------------------------------------------------------------------------
4188
4189 // Transaction 5: request a URL in MyRealm, but the server rejects the
4190 // cached identity. Should invalidate and re-prompt.
4191 {
[email protected]1c773ea12009-04-28 19:58:424192 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234193 request.method = "GET";
4194 request.url = GURL("http://www.google.com/p/q/t");
4195 request.load_flags = 0;
4196
[email protected]cb9bf6ca2011-01-28 13:15:274197 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4198
[email protected]f9ee6b52008-11-08 06:46:234199 MockWrite data_writes1[] = {
4200 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4201 "Host: www.google.com\r\n"
4202 "Connection: keep-alive\r\n\r\n"),
4203 };
4204
4205 MockRead data_reads1[] = {
4206 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4207 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4208 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424209 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234210 };
4211
4212 // Resend with authorization from cache for MyRealm.
4213 MockWrite data_writes2[] = {
4214 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4215 "Host: www.google.com\r\n"
4216 "Connection: keep-alive\r\n"
4217 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4218 };
4219
4220 // Sever rejects the authorization.
4221 MockRead data_reads2[] = {
4222 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4223 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4224 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424225 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234226 };
4227
4228 // At this point we should prompt for new credentials for MyRealm.
4229 // Restart with username=foo3, password=foo4.
4230 MockWrite data_writes3[] = {
4231 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4232 "Host: www.google.com\r\n"
4233 "Connection: keep-alive\r\n"
4234 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4235 };
4236
4237 // Sever accepts the authorization.
4238 MockRead data_reads3[] = {
4239 MockRead("HTTP/1.0 200 OK\r\n"),
4240 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424241 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234242 };
4243
[email protected]31a2bfe2010-02-09 08:03:394244 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4245 data_writes1, arraysize(data_writes1));
4246 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4247 data_writes2, arraysize(data_writes2));
4248 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4249 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594250 session_deps.socket_factory.AddSocketDataProvider(&data1);
4251 session_deps.socket_factory.AddSocketDataProvider(&data2);
4252 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234253
[email protected]49639fa2011-12-20 23:22:414254 TestCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234255
[email protected]49639fa2011-12-20 23:22:414256 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424257 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234258
4259 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424260 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234261
[email protected]0757e7702009-03-27 04:00:224262 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]49639fa2011-12-20 23:22:414263 TestCompletionCallback callback2;
4264 rv = trans->RestartWithAuth(AuthCredentials(), callback2.callback());
[email protected]1c773ea12009-04-28 19:58:424265 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224266 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424267 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224268 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4269
[email protected]1c773ea12009-04-28 19:58:424270 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504271 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044272 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:234273
[email protected]49639fa2011-12-20 23:22:414274 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234275
[email protected]49639fa2011-12-20 23:22:414276 rv = trans->RestartWithAuth(
4277 AuthCredentials(kFoo3, kBar3), callback3.callback());
[email protected]1c773ea12009-04-28 19:58:424278 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234279
[email protected]0757e7702009-03-27 04:00:224280 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424281 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234282
4283 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504284 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234285 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4286 EXPECT_EQ(100, response->headers->GetContentLength());
4287 }
4288}
[email protected]89ceba9a2009-03-21 03:46:064289
[email protected]3c32c5f2010-05-18 15:18:124290// Tests that nonce count increments when multiple auth attempts
4291// are started with the same nonce.
4292TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4293 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444294 HttpAuthHandlerDigest::Factory* digest_factory =
4295 new HttpAuthHandlerDigest::Factory();
4296 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4297 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4298 digest_factory->set_nonce_generator(nonce_generator);
4299 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274300 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124301
4302 // Transaction 1: authenticate (foo, bar) on MyRealm1
4303 {
[email protected]3c32c5f2010-05-18 15:18:124304 HttpRequestInfo request;
4305 request.method = "GET";
4306 request.url = GURL("http://www.google.com/x/y/z");
4307 request.load_flags = 0;
4308
[email protected]cb9bf6ca2011-01-28 13:15:274309 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4310
[email protected]3c32c5f2010-05-18 15:18:124311 MockWrite data_writes1[] = {
4312 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4313 "Host: www.google.com\r\n"
4314 "Connection: keep-alive\r\n\r\n"),
4315 };
4316
4317 MockRead data_reads1[] = {
4318 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4319 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4320 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4321 MockRead(false, OK),
4322 };
4323
4324 // Resend with authorization (username=foo, password=bar)
4325 MockWrite data_writes2[] = {
4326 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4327 "Host: www.google.com\r\n"
4328 "Connection: keep-alive\r\n"
4329 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4330 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4331 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4332 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4333 };
4334
4335 // Sever accepts the authorization.
4336 MockRead data_reads2[] = {
4337 MockRead("HTTP/1.0 200 OK\r\n"),
4338 MockRead(false, OK),
4339 };
4340
4341 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4342 data_writes1, arraysize(data_writes1));
4343 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4344 data_writes2, arraysize(data_writes2));
4345 session_deps.socket_factory.AddSocketDataProvider(&data1);
4346 session_deps.socket_factory.AddSocketDataProvider(&data2);
4347
[email protected]49639fa2011-12-20 23:22:414348 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124349
[email protected]49639fa2011-12-20 23:22:414350 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124351 EXPECT_EQ(ERR_IO_PENDING, rv);
4352
4353 rv = callback1.WaitForResult();
4354 EXPECT_EQ(OK, rv);
4355
4356 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504357 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044358 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:124359
[email protected]49639fa2011-12-20 23:22:414360 TestCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:124361
[email protected]49639fa2011-12-20 23:22:414362 rv = trans->RestartWithAuth(
4363 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]3c32c5f2010-05-18 15:18:124364 EXPECT_EQ(ERR_IO_PENDING, rv);
4365
4366 rv = callback2.WaitForResult();
4367 EXPECT_EQ(OK, rv);
4368
4369 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504370 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124371 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4372 }
4373
4374 // ------------------------------------------------------------------------
4375
4376 // Transaction 2: Request another resource in digestive's protection space.
4377 // This will preemptively add an Authorization header which should have an
4378 // "nc" value of 2 (as compared to 1 in the first use.
4379 {
[email protected]3c32c5f2010-05-18 15:18:124380 HttpRequestInfo request;
4381 request.method = "GET";
4382 // Note that Transaction 1 was at /x/y/z, so this is in the same
4383 // protection space as digest.
4384 request.url = GURL("http://www.google.com/x/y/a/b");
4385 request.load_flags = 0;
4386
[email protected]cb9bf6ca2011-01-28 13:15:274387 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4388
[email protected]3c32c5f2010-05-18 15:18:124389 MockWrite data_writes1[] = {
4390 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4391 "Host: www.google.com\r\n"
4392 "Connection: keep-alive\r\n"
4393 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4394 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4395 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4396 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4397 };
4398
4399 // Sever accepts the authorization.
4400 MockRead data_reads1[] = {
4401 MockRead("HTTP/1.0 200 OK\r\n"),
4402 MockRead("Content-Length: 100\r\n\r\n"),
4403 MockRead(false, OK),
4404 };
4405
4406 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4407 data_writes1, arraysize(data_writes1));
4408 session_deps.socket_factory.AddSocketDataProvider(&data1);
4409
[email protected]49639fa2011-12-20 23:22:414410 TestCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124411
[email protected]49639fa2011-12-20 23:22:414412 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]3c32c5f2010-05-18 15:18:124413 EXPECT_EQ(ERR_IO_PENDING, rv);
4414
4415 rv = callback1.WaitForResult();
4416 EXPECT_EQ(OK, rv);
4417
4418 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504419 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124420 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4421 }
4422}
4423
[email protected]89ceba9a2009-03-21 03:46:064424// Test the ResetStateForRestart() private method.
4425TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4426 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594427 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404428 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434429 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064430
4431 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064432 trans->read_buf_ = new IOBuffer(15);
4433 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204434 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064435
4436 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144437 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574438 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:084439 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:574440 response->response_time = base::Time::Now();
4441 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064442
4443 { // Setup state for response_.vary_data
4444 HttpRequestInfo request;
4445 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4446 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274447 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434448 request.extra_headers.SetHeader("Foo", "1");
4449 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574450 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064451 }
4452
4453 // Cause the above state to be reset.
4454 trans->ResetStateForRestart();
4455
4456 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074457 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064458 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204459 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574460 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4461 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044462 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:084463 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:574464 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064465}
4466
[email protected]bacff652009-03-31 17:50:334467// Test HTTPS connections to a site with a bad certificate
4468TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334469 HttpRequestInfo request;
4470 request.method = "GET";
4471 request.url = GURL("https://www.google.com/");
4472 request.load_flags = 0;
4473
[email protected]cb9bf6ca2011-01-28 13:15:274474 SessionDependencies session_deps;
4475 scoped_ptr<HttpTransaction> trans(
4476 new HttpNetworkTransaction(CreateSession(&session_deps)));
4477
[email protected]bacff652009-03-31 17:50:334478 MockWrite data_writes[] = {
4479 MockWrite("GET / HTTP/1.1\r\n"
4480 "Host: www.google.com\r\n"
4481 "Connection: keep-alive\r\n\r\n"),
4482 };
4483
4484 MockRead data_reads[] = {
4485 MockRead("HTTP/1.0 200 OK\r\n"),
4486 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4487 MockRead("Content-Length: 100\r\n\r\n"),
4488 MockRead(false, OK),
4489 };
4490
[email protected]5ecc992a42009-11-11 01:41:594491 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394492 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4493 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594494 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4495 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334496
[email protected]5ecc992a42009-11-11 01:41:594497 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4498 session_deps.socket_factory.AddSocketDataProvider(&data);
4499 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4500 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334501
[email protected]49639fa2011-12-20 23:22:414502 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334503
[email protected]49639fa2011-12-20 23:22:414504 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334505 EXPECT_EQ(ERR_IO_PENDING, rv);
4506
4507 rv = callback.WaitForResult();
4508 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4509
[email protected]49639fa2011-12-20 23:22:414510 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334511 EXPECT_EQ(ERR_IO_PENDING, rv);
4512
4513 rv = callback.WaitForResult();
4514 EXPECT_EQ(OK, rv);
4515
4516 const HttpResponseInfo* response = trans->GetResponseInfo();
4517
[email protected]fe2255a2011-09-20 19:37:504518 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334519 EXPECT_EQ(100, response->headers->GetContentLength());
4520}
4521
4522// Test HTTPS connections to a site with a bad certificate, going through a
4523// proxy
4524TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004525 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334526
4527 HttpRequestInfo request;
4528 request.method = "GET";
4529 request.url = GURL("https://www.google.com/");
4530 request.load_flags = 0;
4531
4532 MockWrite proxy_writes[] = {
4533 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454534 "Host: www.google.com\r\n"
4535 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334536 };
4537
4538 MockRead proxy_reads[] = {
4539 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424540 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334541 };
4542
4543 MockWrite data_writes[] = {
4544 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454545 "Host: www.google.com\r\n"
4546 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334547 MockWrite("GET / HTTP/1.1\r\n"
4548 "Host: www.google.com\r\n"
4549 "Connection: keep-alive\r\n\r\n"),
4550 };
4551
4552 MockRead data_reads[] = {
4553 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4554 MockRead("HTTP/1.0 200 OK\r\n"),
4555 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4556 MockRead("Content-Length: 100\r\n\r\n"),
4557 MockRead(false, OK),
4558 };
4559
[email protected]31a2bfe2010-02-09 08:03:394560 StaticSocketDataProvider ssl_bad_certificate(
4561 proxy_reads, arraysize(proxy_reads),
4562 proxy_writes, arraysize(proxy_writes));
4563 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4564 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594565 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4566 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334567
[email protected]5ecc992a42009-11-11 01:41:594568 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4569 session_deps.socket_factory.AddSocketDataProvider(&data);
4570 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4571 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334572
[email protected]49639fa2011-12-20 23:22:414573 TestCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334574
4575 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594576 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334577
[email protected]d207a5f2009-06-04 05:28:404578 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434579 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334580
[email protected]49639fa2011-12-20 23:22:414581 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]bacff652009-03-31 17:50:334582 EXPECT_EQ(ERR_IO_PENDING, rv);
4583
4584 rv = callback.WaitForResult();
4585 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4586
[email protected]49639fa2011-12-20 23:22:414587 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]bacff652009-03-31 17:50:334588 EXPECT_EQ(ERR_IO_PENDING, rv);
4589
4590 rv = callback.WaitForResult();
4591 EXPECT_EQ(OK, rv);
4592
4593 const HttpResponseInfo* response = trans->GetResponseInfo();
4594
[email protected]fe2255a2011-09-20 19:37:504595 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334596 EXPECT_EQ(100, response->headers->GetContentLength());
4597 }
4598}
4599
[email protected]2df19bb2010-08-25 20:13:464600
4601// Test HTTPS connections to a site, going through an HTTPS proxy
4602TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114603 SessionDependencies session_deps(ProxyService::CreateFixed(
4604 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464605
4606 HttpRequestInfo request;
4607 request.method = "GET";
4608 request.url = GURL("https://www.google.com/");
4609 request.load_flags = 0;
4610
4611 MockWrite data_writes[] = {
4612 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4613 "Host: www.google.com\r\n"
4614 "Proxy-Connection: keep-alive\r\n\r\n"),
4615 MockWrite("GET / HTTP/1.1\r\n"
4616 "Host: www.google.com\r\n"
4617 "Connection: keep-alive\r\n\r\n"),
4618 };
4619
4620 MockRead data_reads[] = {
4621 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4622 MockRead("HTTP/1.1 200 OK\r\n"),
4623 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4624 MockRead("Content-Length: 100\r\n\r\n"),
4625 MockRead(false, OK),
4626 };
4627
4628 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4629 data_writes, arraysize(data_writes));
4630 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4631 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4632
4633 session_deps.socket_factory.AddSocketDataProvider(&data);
4634 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4635 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4636
[email protected]49639fa2011-12-20 23:22:414637 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464638
4639 scoped_ptr<HttpTransaction> trans(
4640 new HttpNetworkTransaction(CreateSession(&session_deps)));
4641
[email protected]49639fa2011-12-20 23:22:414642 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464643 EXPECT_EQ(ERR_IO_PENDING, rv);
4644
4645 rv = callback.WaitForResult();
4646 EXPECT_EQ(OK, rv);
4647 const HttpResponseInfo* response = trans->GetResponseInfo();
4648
[email protected]fe2255a2011-09-20 19:37:504649 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464650
4651 EXPECT_TRUE(response->headers->IsKeepAlive());
4652 EXPECT_EQ(200, response->headers->response_code());
4653 EXPECT_EQ(100, response->headers->GetContentLength());
4654 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4655}
4656
[email protected]511f6f52010-12-17 03:58:294657// Test an HTTPS Proxy's ability to redirect a CONNECT request
4658TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4659 SessionDependencies session_deps(
4660 ProxyService::CreateFixed("https://proxy:70"));
4661
4662 HttpRequestInfo request;
4663 request.method = "GET";
4664 request.url = GURL("https://www.google.com/");
4665 request.load_flags = 0;
4666
4667 MockWrite data_writes[] = {
4668 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4669 "Host: www.google.com\r\n"
4670 "Proxy-Connection: keep-alive\r\n\r\n"),
4671 };
4672
4673 MockRead data_reads[] = {
4674 MockRead("HTTP/1.1 302 Redirect\r\n"),
4675 MockRead("Location: http://login.example.com/\r\n"),
4676 MockRead("Content-Length: 0\r\n\r\n"),
4677 MockRead(false, OK),
4678 };
4679
4680 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4681 data_writes, arraysize(data_writes));
4682 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4683
4684 session_deps.socket_factory.AddSocketDataProvider(&data);
4685 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4686
[email protected]49639fa2011-12-20 23:22:414687 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294688
4689 scoped_ptr<HttpTransaction> trans(
4690 new HttpNetworkTransaction(CreateSession(&session_deps)));
4691
[email protected]49639fa2011-12-20 23:22:414692 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294693 EXPECT_EQ(ERR_IO_PENDING, rv);
4694
4695 rv = callback.WaitForResult();
4696 EXPECT_EQ(OK, rv);
4697 const HttpResponseInfo* response = trans->GetResponseInfo();
4698
[email protected]fe2255a2011-09-20 19:37:504699 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294700
4701 EXPECT_EQ(302, response->headers->response_code());
4702 std::string url;
4703 EXPECT_TRUE(response->headers->IsRedirect(&url));
4704 EXPECT_EQ("http://login.example.com/", url);
4705}
4706
4707// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4708TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4709 SessionDependencies session_deps(
4710 ProxyService::CreateFixed("https://proxy:70"));
4711
4712 HttpRequestInfo request;
4713 request.method = "GET";
4714 request.url = GURL("https://www.google.com/");
4715 request.load_flags = 0;
4716
4717 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4718 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4719 MockWrite data_writes[] = {
4720 CreateMockWrite(*conn.get(), 0, false),
4721 };
4722
4723 static const char* const kExtraHeaders[] = {
4724 "location",
4725 "http://login.example.com/",
4726 };
4727 scoped_ptr<spdy::SpdyFrame> resp(
4728 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4729 arraysize(kExtraHeaders)/2, 1));
4730 MockRead data_reads[] = {
4731 CreateMockRead(*resp.get(), 1, false),
4732 MockRead(true, 0, 2), // EOF
4733 };
4734
[email protected]a1595312012-01-22 03:25:044735 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294736 new DelayedSocketData(
4737 1, // wait for one write to finish before reading.
4738 data_reads, arraysize(data_reads),
4739 data_writes, arraysize(data_writes)));
4740 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4741 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:204742 proxy_ssl.next_proto = "spdy/2.1";
[email protected]511f6f52010-12-17 03:58:294743 proxy_ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:204744 proxy_ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]511f6f52010-12-17 03:58:294745
4746 session_deps.socket_factory.AddSocketDataProvider(data.get());
4747 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4748
[email protected]49639fa2011-12-20 23:22:414749 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294750
4751 scoped_ptr<HttpTransaction> trans(
4752 new HttpNetworkTransaction(CreateSession(&session_deps)));
4753
[email protected]49639fa2011-12-20 23:22:414754 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294755 EXPECT_EQ(ERR_IO_PENDING, rv);
4756
4757 rv = callback.WaitForResult();
4758 EXPECT_EQ(OK, rv);
4759 const HttpResponseInfo* response = trans->GetResponseInfo();
4760
[email protected]fe2255a2011-09-20 19:37:504761 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294762
4763 EXPECT_EQ(302, response->headers->response_code());
4764 std::string url;
4765 EXPECT_TRUE(response->headers->IsRedirect(&url));
4766 EXPECT_EQ("http://login.example.com/", url);
4767}
4768
4769// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4770TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4771 SessionDependencies session_deps(
4772 ProxyService::CreateFixed("https://proxy:70"));
4773
4774 HttpRequestInfo request;
4775 request.method = "GET";
4776 request.url = GURL("https://www.google.com/");
4777 request.load_flags = 0;
4778
4779 MockWrite data_writes[] = {
4780 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4781 "Host: www.google.com\r\n"
4782 "Proxy-Connection: keep-alive\r\n\r\n"),
4783 };
4784
4785 MockRead data_reads[] = {
4786 MockRead("HTTP/1.1 404 Not Found\r\n"),
4787 MockRead("Content-Length: 23\r\n\r\n"),
4788 MockRead("The host does not exist"),
4789 MockRead(false, OK),
4790 };
4791
4792 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4793 data_writes, arraysize(data_writes));
4794 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4795
4796 session_deps.socket_factory.AddSocketDataProvider(&data);
4797 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4798
[email protected]49639fa2011-12-20 23:22:414799 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294800
4801 scoped_ptr<HttpTransaction> trans(
4802 new HttpNetworkTransaction(CreateSession(&session_deps)));
4803
[email protected]49639fa2011-12-20 23:22:414804 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294805 EXPECT_EQ(ERR_IO_PENDING, rv);
4806
4807 rv = callback.WaitForResult();
4808 EXPECT_EQ(OK, rv);
4809 const HttpResponseInfo* response = trans->GetResponseInfo();
4810
[email protected]fe2255a2011-09-20 19:37:504811 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294812
4813 EXPECT_EQ(404, response->headers->response_code());
4814 EXPECT_EQ(23, response->headers->GetContentLength());
4815 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4816 EXPECT_FALSE(response->ssl_info.is_valid());
4817
4818 std::string response_data;
4819 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4820 EXPECT_EQ("The host does not exist", response_data);
4821}
4822
4823// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4824// request
4825TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4826 SessionDependencies session_deps(
4827 ProxyService::CreateFixed("https://proxy:70"));
4828
4829 HttpRequestInfo request;
4830 request.method = "GET";
4831 request.url = GURL("https://www.google.com/");
4832 request.load_flags = 0;
4833
4834 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4835 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4836 MockWrite data_writes[] = {
4837 CreateMockWrite(*conn.get(), 0, false),
4838 };
4839
4840 static const char* const kExtraHeaders[] = {
4841 "location",
4842 "http://login.example.com/",
4843 };
4844 scoped_ptr<spdy::SpdyFrame> resp(
4845 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4846 arraysize(kExtraHeaders)/2, 1));
4847 scoped_ptr<spdy::SpdyFrame> body(
4848 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4849 MockRead data_reads[] = {
4850 CreateMockRead(*resp.get(), 1, false),
4851 CreateMockRead(*body.get(), 2, false),
4852 MockRead(true, 0, 3), // EOF
4853 };
4854
[email protected]a1595312012-01-22 03:25:044855 scoped_ptr<DelayedSocketData> data(
[email protected]511f6f52010-12-17 03:58:294856 new DelayedSocketData(
4857 1, // wait for one write to finish before reading.
4858 data_reads, arraysize(data_reads),
4859 data_writes, arraysize(data_writes)));
4860 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4861 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:204862 proxy_ssl.next_proto = "spdy/2.1";
[email protected]511f6f52010-12-17 03:58:294863 proxy_ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:204864 proxy_ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]511f6f52010-12-17 03:58:294865
4866 session_deps.socket_factory.AddSocketDataProvider(data.get());
4867 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4868
[email protected]49639fa2011-12-20 23:22:414869 TestCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294870
4871 scoped_ptr<HttpTransaction> trans(
4872 new HttpNetworkTransaction(CreateSession(&session_deps)));
4873
[email protected]49639fa2011-12-20 23:22:414874 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]511f6f52010-12-17 03:58:294875 EXPECT_EQ(ERR_IO_PENDING, rv);
4876
4877 rv = callback.WaitForResult();
4878 EXPECT_EQ(OK, rv);
4879 const HttpResponseInfo* response = trans->GetResponseInfo();
4880
[email protected]fe2255a2011-09-20 19:37:504881 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294882
4883 EXPECT_EQ(404, response->headers->response_code());
4884 EXPECT_FALSE(response->ssl_info.is_valid());
4885
4886 std::string response_data;
4887 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4888 EXPECT_EQ("The host does not exist", response_data);
4889}
4890
[email protected]2df19bb2010-08-25 20:13:464891// Test HTTPS connections to a site with a bad certificate, going through an
4892// HTTPS proxy
4893TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114894 SessionDependencies session_deps(ProxyService::CreateFixed(
4895 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464896
4897 HttpRequestInfo request;
4898 request.method = "GET";
4899 request.url = GURL("https://www.google.com/");
4900 request.load_flags = 0;
4901
4902 // Attempt to fetch the URL from a server with a bad cert
4903 MockWrite bad_cert_writes[] = {
4904 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4905 "Host: www.google.com\r\n"
4906 "Proxy-Connection: keep-alive\r\n\r\n"),
4907 };
4908
4909 MockRead bad_cert_reads[] = {
4910 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4911 MockRead(false, OK)
4912 };
4913
4914 // Attempt to fetch the URL with a good cert
4915 MockWrite good_data_writes[] = {
4916 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4917 "Host: www.google.com\r\n"
4918 "Proxy-Connection: keep-alive\r\n\r\n"),
4919 MockWrite("GET / HTTP/1.1\r\n"
4920 "Host: www.google.com\r\n"
4921 "Connection: keep-alive\r\n\r\n"),
4922 };
4923
4924 MockRead good_cert_reads[] = {
4925 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4926 MockRead("HTTP/1.0 200 OK\r\n"),
4927 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4928 MockRead("Content-Length: 100\r\n\r\n"),
4929 MockRead(false, OK),
4930 };
4931
4932 StaticSocketDataProvider ssl_bad_certificate(
4933 bad_cert_reads, arraysize(bad_cert_reads),
4934 bad_cert_writes, arraysize(bad_cert_writes));
4935 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4936 good_data_writes, arraysize(good_data_writes));
4937 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4938 SSLSocketDataProvider ssl(true, OK);
4939
4940 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4941 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4942 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4943 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4944
4945 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4946 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4947 session_deps.socket_factory.AddSocketDataProvider(&data);
4948 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4949
[email protected]49639fa2011-12-20 23:22:414950 TestCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464951
4952 scoped_ptr<HttpTransaction> trans(
4953 new HttpNetworkTransaction(CreateSession(&session_deps)));
4954
[email protected]49639fa2011-12-20 23:22:414955 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2df19bb2010-08-25 20:13:464956 EXPECT_EQ(ERR_IO_PENDING, rv);
4957
4958 rv = callback.WaitForResult();
4959 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4960
[email protected]49639fa2011-12-20 23:22:414961 rv = trans->RestartIgnoringLastError(callback.callback());
[email protected]2df19bb2010-08-25 20:13:464962 EXPECT_EQ(ERR_IO_PENDING, rv);
4963
4964 rv = callback.WaitForResult();
4965 EXPECT_EQ(OK, rv);
4966
4967 const HttpResponseInfo* response = trans->GetResponseInfo();
4968
[email protected]fe2255a2011-09-20 19:37:504969 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464970 EXPECT_EQ(100, response->headers->GetContentLength());
4971}
4972
[email protected]1c773ea12009-04-28 19:58:424973TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424974 HttpRequestInfo request;
4975 request.method = "GET";
4976 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434977 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4978 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424979
[email protected]cb9bf6ca2011-01-28 13:15:274980 SessionDependencies session_deps;
4981 scoped_ptr<HttpTransaction> trans(
4982 new HttpNetworkTransaction(CreateSession(&session_deps)));
4983
[email protected]1c773ea12009-04-28 19:58:424984 MockWrite data_writes[] = {
4985 MockWrite("GET / HTTP/1.1\r\n"
4986 "Host: www.google.com\r\n"
4987 "Connection: keep-alive\r\n"
4988 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4989 };
4990
4991 // Lastly, the server responds with the actual content.
4992 MockRead data_reads[] = {
4993 MockRead("HTTP/1.0 200 OK\r\n"),
4994 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4995 MockRead("Content-Length: 100\r\n\r\n"),
4996 MockRead(false, OK),
4997 };
4998
[email protected]31a2bfe2010-02-09 08:03:394999 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5000 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595001 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425002
[email protected]49639fa2011-12-20 23:22:415003 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425004
[email protected]49639fa2011-12-20 23:22:415005 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425006 EXPECT_EQ(ERR_IO_PENDING, rv);
5007
5008 rv = callback.WaitForResult();
5009 EXPECT_EQ(OK, rv);
5010}
5011
[email protected]da81f132010-08-18 23:39:295012TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:295013 HttpRequestInfo request;
5014 request.method = "GET";
5015 request.url = GURL("https://www.google.com/");
5016 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
5017 "Chromium Ultra Awesome X Edition");
5018
[email protected]cb9bf6ca2011-01-28 13:15:275019 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
5020 scoped_ptr<HttpTransaction> trans(
5021 new HttpNetworkTransaction(CreateSession(&session_deps)));
5022
[email protected]da81f132010-08-18 23:39:295023 MockWrite data_writes[] = {
5024 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
5025 "Host: www.google.com\r\n"
5026 "Proxy-Connection: keep-alive\r\n"
5027 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
5028 };
5029 MockRead data_reads[] = {
5030 // Return an error, so the transaction stops here (this test isn't
5031 // interested in the rest).
5032 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
5033 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5034 MockRead("Proxy-Connection: close\r\n\r\n"),
5035 };
5036
5037 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5038 data_writes, arraysize(data_writes));
5039 session_deps.socket_factory.AddSocketDataProvider(&data);
5040
[email protected]49639fa2011-12-20 23:22:415041 TestCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:295042
[email protected]49639fa2011-12-20 23:22:415043 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]da81f132010-08-18 23:39:295044 EXPECT_EQ(ERR_IO_PENDING, rv);
5045
5046 rv = callback.WaitForResult();
5047 EXPECT_EQ(OK, rv);
5048}
5049
[email protected]1c773ea12009-04-28 19:58:425050TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:425051 HttpRequestInfo request;
5052 request.method = "GET";
5053 request.url = GURL("http://www.google.com/");
5054 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:165055 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5056 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:425057
[email protected]cb9bf6ca2011-01-28 13:15:275058 SessionDependencies session_deps;
5059 scoped_ptr<HttpTransaction> trans(
5060 new HttpNetworkTransaction(CreateSession(&session_deps)));
5061
[email protected]1c773ea12009-04-28 19:58:425062 MockWrite data_writes[] = {
5063 MockWrite("GET / HTTP/1.1\r\n"
5064 "Host: www.google.com\r\n"
5065 "Connection: keep-alive\r\n"
5066 "Referer: http://the.previous.site.com/\r\n\r\n"),
5067 };
5068
5069 // Lastly, the server responds with the actual content.
5070 MockRead data_reads[] = {
5071 MockRead("HTTP/1.0 200 OK\r\n"),
5072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5073 MockRead("Content-Length: 100\r\n\r\n"),
5074 MockRead(false, OK),
5075 };
5076
[email protected]31a2bfe2010-02-09 08:03:395077 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5078 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595079 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425080
[email protected]49639fa2011-12-20 23:22:415081 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425082
[email protected]49639fa2011-12-20 23:22:415083 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425084 EXPECT_EQ(ERR_IO_PENDING, rv);
5085
5086 rv = callback.WaitForResult();
5087 EXPECT_EQ(OK, rv);
5088}
5089
5090TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425091 HttpRequestInfo request;
5092 request.method = "POST";
5093 request.url = GURL("http://www.google.com/");
5094
[email protected]cb9bf6ca2011-01-28 13:15:275095 SessionDependencies session_deps;
5096 scoped_ptr<HttpTransaction> trans(
5097 new HttpNetworkTransaction(CreateSession(&session_deps)));
5098
[email protected]1c773ea12009-04-28 19:58:425099 MockWrite data_writes[] = {
5100 MockWrite("POST / HTTP/1.1\r\n"
5101 "Host: www.google.com\r\n"
5102 "Connection: keep-alive\r\n"
5103 "Content-Length: 0\r\n\r\n"),
5104 };
5105
5106 // Lastly, the server responds with the actual content.
5107 MockRead data_reads[] = {
5108 MockRead("HTTP/1.0 200 OK\r\n"),
5109 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5110 MockRead("Content-Length: 100\r\n\r\n"),
5111 MockRead(false, OK),
5112 };
5113
[email protected]31a2bfe2010-02-09 08:03:395114 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5115 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595116 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425117
[email protected]49639fa2011-12-20 23:22:415118 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425119
[email protected]49639fa2011-12-20 23:22:415120 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425121 EXPECT_EQ(ERR_IO_PENDING, rv);
5122
5123 rv = callback.WaitForResult();
5124 EXPECT_EQ(OK, rv);
5125}
5126
5127TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425128 HttpRequestInfo request;
5129 request.method = "PUT";
5130 request.url = GURL("http://www.google.com/");
5131
[email protected]cb9bf6ca2011-01-28 13:15:275132 SessionDependencies session_deps;
5133 scoped_ptr<HttpTransaction> trans(
5134 new HttpNetworkTransaction(CreateSession(&session_deps)));
5135
[email protected]1c773ea12009-04-28 19:58:425136 MockWrite data_writes[] = {
5137 MockWrite("PUT / HTTP/1.1\r\n"
5138 "Host: www.google.com\r\n"
5139 "Connection: keep-alive\r\n"
5140 "Content-Length: 0\r\n\r\n"),
5141 };
5142
5143 // Lastly, the server responds with the actual content.
5144 MockRead data_reads[] = {
5145 MockRead("HTTP/1.0 200 OK\r\n"),
5146 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5147 MockRead("Content-Length: 100\r\n\r\n"),
5148 MockRead(false, OK),
5149 };
5150
[email protected]31a2bfe2010-02-09 08:03:395151 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5152 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595153 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425154
[email protected]49639fa2011-12-20 23:22:415155 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425156
[email protected]49639fa2011-12-20 23:22:415157 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425158 EXPECT_EQ(ERR_IO_PENDING, rv);
5159
5160 rv = callback.WaitForResult();
5161 EXPECT_EQ(OK, rv);
5162}
5163
5164TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425165 HttpRequestInfo request;
5166 request.method = "HEAD";
5167 request.url = GURL("http://www.google.com/");
5168
[email protected]cb9bf6ca2011-01-28 13:15:275169 SessionDependencies session_deps;
5170 scoped_ptr<HttpTransaction> trans(
5171 new HttpNetworkTransaction(CreateSession(&session_deps)));
5172
[email protected]1c773ea12009-04-28 19:58:425173 MockWrite data_writes[] = {
5174 MockWrite("HEAD / HTTP/1.1\r\n"
5175 "Host: www.google.com\r\n"
5176 "Connection: keep-alive\r\n"
5177 "Content-Length: 0\r\n\r\n"),
5178 };
5179
5180 // Lastly, the server responds with the actual content.
5181 MockRead data_reads[] = {
5182 MockRead("HTTP/1.0 200 OK\r\n"),
5183 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5184 MockRead("Content-Length: 100\r\n\r\n"),
5185 MockRead(false, OK),
5186 };
5187
[email protected]31a2bfe2010-02-09 08:03:395188 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5189 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595190 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425191
[email protected]49639fa2011-12-20 23:22:415192 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425193
[email protected]49639fa2011-12-20 23:22:415194 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425195 EXPECT_EQ(ERR_IO_PENDING, rv);
5196
5197 rv = callback.WaitForResult();
5198 EXPECT_EQ(OK, rv);
5199}
5200
5201TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425202 HttpRequestInfo request;
5203 request.method = "GET";
5204 request.url = GURL("http://www.google.com/");
5205 request.load_flags = LOAD_BYPASS_CACHE;
5206
[email protected]cb9bf6ca2011-01-28 13:15:275207 SessionDependencies session_deps;
5208 scoped_ptr<HttpTransaction> trans(
5209 new HttpNetworkTransaction(CreateSession(&session_deps)));
5210
[email protected]1c773ea12009-04-28 19:58:425211 MockWrite data_writes[] = {
5212 MockWrite("GET / HTTP/1.1\r\n"
5213 "Host: www.google.com\r\n"
5214 "Connection: keep-alive\r\n"
5215 "Pragma: no-cache\r\n"
5216 "Cache-Control: no-cache\r\n\r\n"),
5217 };
5218
5219 // Lastly, the server responds with the actual content.
5220 MockRead data_reads[] = {
5221 MockRead("HTTP/1.0 200 OK\r\n"),
5222 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5223 MockRead("Content-Length: 100\r\n\r\n"),
5224 MockRead(false, OK),
5225 };
5226
[email protected]31a2bfe2010-02-09 08:03:395227 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5228 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595229 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425230
[email protected]49639fa2011-12-20 23:22:415231 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425232
[email protected]49639fa2011-12-20 23:22:415233 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425234 EXPECT_EQ(ERR_IO_PENDING, rv);
5235
5236 rv = callback.WaitForResult();
5237 EXPECT_EQ(OK, rv);
5238}
5239
5240TEST_F(HttpNetworkTransactionTest,
5241 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425242 HttpRequestInfo request;
5243 request.method = "GET";
5244 request.url = GURL("http://www.google.com/");
5245 request.load_flags = LOAD_VALIDATE_CACHE;
5246
[email protected]cb9bf6ca2011-01-28 13:15:275247 SessionDependencies session_deps;
5248 scoped_ptr<HttpTransaction> trans(
5249 new HttpNetworkTransaction(CreateSession(&session_deps)));
5250
[email protected]1c773ea12009-04-28 19:58:425251 MockWrite data_writes[] = {
5252 MockWrite("GET / HTTP/1.1\r\n"
5253 "Host: www.google.com\r\n"
5254 "Connection: keep-alive\r\n"
5255 "Cache-Control: max-age=0\r\n\r\n"),
5256 };
5257
5258 // Lastly, the server responds with the actual content.
5259 MockRead data_reads[] = {
5260 MockRead("HTTP/1.0 200 OK\r\n"),
5261 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5262 MockRead("Content-Length: 100\r\n\r\n"),
5263 MockRead(false, OK),
5264 };
5265
[email protected]31a2bfe2010-02-09 08:03:395266 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5267 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595268 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425269
[email protected]49639fa2011-12-20 23:22:415270 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425271
[email protected]49639fa2011-12-20 23:22:415272 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425273 EXPECT_EQ(ERR_IO_PENDING, rv);
5274
5275 rv = callback.WaitForResult();
5276 EXPECT_EQ(OK, rv);
5277}
5278
5279TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425280 HttpRequestInfo request;
5281 request.method = "GET";
5282 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435283 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425284
[email protected]cb9bf6ca2011-01-28 13:15:275285 SessionDependencies session_deps;
5286 scoped_ptr<HttpTransaction> trans(
5287 new HttpNetworkTransaction(CreateSession(&session_deps)));
5288
[email protected]1c773ea12009-04-28 19:58:425289 MockWrite data_writes[] = {
5290 MockWrite("GET / HTTP/1.1\r\n"
5291 "Host: www.google.com\r\n"
5292 "Connection: keep-alive\r\n"
5293 "FooHeader: Bar\r\n\r\n"),
5294 };
5295
5296 // Lastly, the server responds with the actual content.
5297 MockRead data_reads[] = {
5298 MockRead("HTTP/1.0 200 OK\r\n"),
5299 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5300 MockRead("Content-Length: 100\r\n\r\n"),
5301 MockRead(false, OK),
5302 };
5303
[email protected]31a2bfe2010-02-09 08:03:395304 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5305 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595306 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425307
[email protected]49639fa2011-12-20 23:22:415308 TestCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425309
[email protected]49639fa2011-12-20 23:22:415310 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425311 EXPECT_EQ(ERR_IO_PENDING, rv);
5312
5313 rv = callback.WaitForResult();
5314 EXPECT_EQ(OK, rv);
5315}
5316
[email protected]270c6412010-03-29 22:02:475317TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475318 HttpRequestInfo request;
5319 request.method = "GET";
5320 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435321 request.extra_headers.SetHeader("referer", "www.foo.com");
5322 request.extra_headers.SetHeader("hEllo", "Kitty");
5323 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475324
[email protected]cb9bf6ca2011-01-28 13:15:275325 SessionDependencies session_deps;
5326 scoped_ptr<HttpTransaction> trans(
5327 new HttpNetworkTransaction(CreateSession(&session_deps)));
5328
[email protected]270c6412010-03-29 22:02:475329 MockWrite data_writes[] = {
5330 MockWrite("GET / HTTP/1.1\r\n"
5331 "Host: www.google.com\r\n"
5332 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165333 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475334 "hEllo: Kitty\r\n"
5335 "FoO: bar\r\n\r\n"),
5336 };
5337
5338 // Lastly, the server responds with the actual content.
5339 MockRead data_reads[] = {
5340 MockRead("HTTP/1.0 200 OK\r\n"),
5341 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5342 MockRead("Content-Length: 100\r\n\r\n"),
5343 MockRead(false, OK),
5344 };
5345
5346 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5347 data_writes, arraysize(data_writes));
5348 session_deps.socket_factory.AddSocketDataProvider(&data);
5349
[email protected]49639fa2011-12-20 23:22:415350 TestCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:475351
[email protected]49639fa2011-12-20 23:22:415352 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]270c6412010-03-29 22:02:475353 EXPECT_EQ(ERR_IO_PENDING, rv);
5354
5355 rv = callback.WaitForResult();
5356 EXPECT_EQ(OK, rv);
5357}
5358
[email protected]ee0b1012012-02-04 04:30:255359#if defined(OS_MACOSX)
5360#define MAYBE_SOCKS4_HTTP_GET FLAKY_SOCKS4_HTTP_GET
5361#else
5362#define MAYBE_SOCKS4_HTTP_GET SOCKS4_HTTP_GET
5363#endif
5364
5365TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275366 HttpRequestInfo request;
5367 request.method = "GET";
5368 request.url = GURL("http://www.google.com/");
5369 request.load_flags = 0;
5370
[email protected]80d6524d2009-08-18 03:58:095371 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005372 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025373
5374 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435375 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025376
[email protected]3cd17242009-06-23 02:59:025377 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5378 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5379
5380 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355381 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025382 MockWrite("GET / HTTP/1.1\r\n"
5383 "Host: www.google.com\r\n"
5384 "Connection: keep-alive\r\n\r\n")
5385 };
5386
5387 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595388 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025389 MockRead("HTTP/1.0 200 OK\r\n"),
5390 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5391 MockRead("Payload"),
5392 MockRead(false, OK)
5393 };
5394
[email protected]31a2bfe2010-02-09 08:03:395395 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5396 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595397 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025398
[email protected]49639fa2011-12-20 23:22:415399 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025400
[email protected]49639fa2011-12-20 23:22:415401 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025402 EXPECT_EQ(ERR_IO_PENDING, rv);
5403
5404 rv = callback.WaitForResult();
5405 EXPECT_EQ(OK, rv);
5406
5407 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505408 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025409
5410 std::string response_text;
5411 rv = ReadTransaction(trans.get(), &response_text);
5412 EXPECT_EQ(OK, rv);
5413 EXPECT_EQ("Payload", response_text);
5414}
5415
[email protected]ee0b1012012-02-04 04:30:255416#if defined(OS_MACOSX)
5417#define MAYBE_SOCKS4_SSL_GET FLAKY_SOCKS4_SSL_GET
5418#else
5419#define MAYBE_SOCKS4_SSL_GET SOCKS4_SSL_GET
5420#endif
5421
5422TEST_F(HttpNetworkTransactionTest, MAYBE_SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275423 HttpRequestInfo request;
5424 request.method = "GET";
5425 request.url = GURL("https://www.google.com/");
5426 request.load_flags = 0;
5427
[email protected]80d6524d2009-08-18 03:58:095428 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005429 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025430
5431 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435432 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025433
[email protected]3cd17242009-06-23 02:59:025434 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5435 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5436
5437 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355438 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5439 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025440 MockWrite("GET / HTTP/1.1\r\n"
5441 "Host: www.google.com\r\n"
5442 "Connection: keep-alive\r\n\r\n")
5443 };
5444
5445 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355446 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5447 arraysize(read_buffer)),
5448 MockRead("HTTP/1.0 200 OK\r\n"),
5449 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5450 MockRead("Payload"),
5451 MockRead(false, OK)
5452 };
5453
[email protected]31a2bfe2010-02-09 08:03:395454 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5455 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595456 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355457
[email protected]5ecc992a42009-11-11 01:41:595458 SSLSocketDataProvider ssl(true, OK);
5459 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355460
[email protected]49639fa2011-12-20 23:22:415461 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355462
[email protected]49639fa2011-12-20 23:22:415463 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355464 EXPECT_EQ(ERR_IO_PENDING, rv);
5465
5466 rv = callback.WaitForResult();
5467 EXPECT_EQ(OK, rv);
5468
5469 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505470 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355471
5472 std::string response_text;
5473 rv = ReadTransaction(trans.get(), &response_text);
5474 EXPECT_EQ(OK, rv);
5475 EXPECT_EQ("Payload", response_text);
5476}
5477
5478TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275479 HttpRequestInfo request;
5480 request.method = "GET";
5481 request.url = GURL("http://www.google.com/");
5482 request.load_flags = 0;
5483
[email protected]80d6524d2009-08-18 03:58:095484 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005485 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355486
5487 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435488 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355489
[email protected]e0c27be2009-07-15 13:09:355490 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5491 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375492 const char kSOCKS5OkRequest[] = {
5493 0x05, // Version
5494 0x01, // Command (CONNECT)
5495 0x00, // Reserved.
5496 0x03, // Address type (DOMAINNAME).
5497 0x0E, // Length of domain (14)
5498 // Domain string:
5499 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5500 0x00, 0x50, // 16-bit port (80)
5501 };
[email protected]e0c27be2009-07-15 13:09:355502 const char kSOCKS5OkResponse[] =
5503 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5504
5505 MockWrite data_writes[] = {
5506 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5507 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5508 MockWrite("GET / HTTP/1.1\r\n"
5509 "Host: www.google.com\r\n"
5510 "Connection: keep-alive\r\n\r\n")
5511 };
5512
5513 MockRead data_reads[] = {
5514 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5515 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5516 MockRead("HTTP/1.0 200 OK\r\n"),
5517 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5518 MockRead("Payload"),
5519 MockRead(false, OK)
5520 };
5521
[email protected]31a2bfe2010-02-09 08:03:395522 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5523 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595524 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355525
[email protected]49639fa2011-12-20 23:22:415526 TestCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355527
[email protected]49639fa2011-12-20 23:22:415528 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355529 EXPECT_EQ(ERR_IO_PENDING, rv);
5530
5531 rv = callback.WaitForResult();
5532 EXPECT_EQ(OK, rv);
5533
5534 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505535 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355536
5537 std::string response_text;
5538 rv = ReadTransaction(trans.get(), &response_text);
5539 EXPECT_EQ(OK, rv);
5540 EXPECT_EQ("Payload", response_text);
5541}
5542
5543TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275544 HttpRequestInfo request;
5545 request.method = "GET";
5546 request.url = GURL("https://www.google.com/");
5547 request.load_flags = 0;
5548
[email protected]80d6524d2009-08-18 03:58:095549 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005550 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355551
5552 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435553 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355554
[email protected]e0c27be2009-07-15 13:09:355555 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5556 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375557 const unsigned char kSOCKS5OkRequest[] = {
5558 0x05, // Version
5559 0x01, // Command (CONNECT)
5560 0x00, // Reserved.
5561 0x03, // Address type (DOMAINNAME).
5562 0x0E, // Length of domain (14)
5563 // Domain string:
5564 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5565 0x01, 0xBB, // 16-bit port (443)
5566 };
5567
[email protected]e0c27be2009-07-15 13:09:355568 const char kSOCKS5OkResponse[] =
5569 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5570
5571 MockWrite data_writes[] = {
5572 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5573 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5574 arraysize(kSOCKS5OkRequest)),
5575 MockWrite("GET / HTTP/1.1\r\n"
5576 "Host: www.google.com\r\n"
5577 "Connection: keep-alive\r\n\r\n")
5578 };
5579
5580 MockRead data_reads[] = {
5581 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5582 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025583 MockRead("HTTP/1.0 200 OK\r\n"),
5584 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5585 MockRead("Payload"),
5586 MockRead(false, OK)
5587 };
5588
[email protected]31a2bfe2010-02-09 08:03:395589 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5590 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595591 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025592
[email protected]5ecc992a42009-11-11 01:41:595593 SSLSocketDataProvider ssl(true, OK);
5594 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025595
[email protected]49639fa2011-12-20 23:22:415596 TestCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025597
[email protected]49639fa2011-12-20 23:22:415598 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025599 EXPECT_EQ(ERR_IO_PENDING, rv);
5600
5601 rv = callback.WaitForResult();
5602 EXPECT_EQ(OK, rv);
5603
5604 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505605 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025606
5607 std::string response_text;
5608 rv = ReadTransaction(trans.get(), &response_text);
5609 EXPECT_EQ(OK, rv);
5610 EXPECT_EQ("Payload", response_text);
5611}
5612
[email protected]04e5be32009-06-26 20:00:315613// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065614
5615struct GroupNameTest {
5616 std::string proxy_server;
5617 std::string url;
5618 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185619 bool ssl;
[email protected]2d731a32010-04-29 01:04:065620};
5621
5622scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025623 SessionDependencies* session_deps) {
5624 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065625
[email protected]17291a022011-10-10 07:32:535626 HttpServerProperties* http_server_properties =
5627 session->http_server_properties();
5628 http_server_properties->SetAlternateProtocol(
[email protected]2d731a32010-04-29 01:04:065629 HostPortPair("host.with.alternate", 80), 443,
[email protected]1ad77dc2012-01-27 03:51:205630 NPN_SPDY_21);
[email protected]2d731a32010-04-29 01:04:065631
5632 return session;
5633}
5634
5635int GroupNameTransactionHelper(
5636 const std::string& url,
5637 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065638 HttpRequestInfo request;
5639 request.method = "GET";
5640 request.url = GURL(url);
5641 request.load_flags = 0;
5642
[email protected]cb9bf6ca2011-01-28 13:15:275643 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5644
[email protected]49639fa2011-12-20 23:22:415645 TestCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:065646
5647 // We do not complete this request, the dtor will clean the transaction up.
[email protected]49639fa2011-12-20 23:22:415648 return trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d731a32010-04-29 01:04:065649}
5650
5651TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5652 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315653 {
[email protected]2d731a32010-04-29 01:04:065654 "", // unused
[email protected]04e5be32009-06-26 20:00:315655 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545656 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185657 false,
[email protected]2ff8b312010-04-26 22:20:545658 },
5659 {
[email protected]2d731a32010-04-29 01:04:065660 "", // unused
[email protected]2ff8b312010-04-26 22:20:545661 "http://[2001:1418:13:1::25]/direct",
5662 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185663 false,
[email protected]04e5be32009-06-26 20:00:315664 },
[email protected]04e5be32009-06-26 20:00:315665
5666 // SSL Tests
5667 {
[email protected]2d731a32010-04-29 01:04:065668 "", // unused
[email protected]04e5be32009-06-26 20:00:315669 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025670 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185671 true,
[email protected]04e5be32009-06-26 20:00:315672 },
5673 {
[email protected]2d731a32010-04-29 01:04:065674 "", // unused
5675 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025676 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185677 true,
[email protected]04e5be32009-06-26 20:00:315678 },
5679 {
[email protected]2d731a32010-04-29 01:04:065680 "", // unused
[email protected]2ff8b312010-04-26 22:20:545681 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025682 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185683 true,
[email protected]2ff8b312010-04-26 22:20:545684 },
[email protected]2d731a32010-04-29 01:04:065685 };
[email protected]2ff8b312010-04-26 22:20:545686
[email protected]8e6441ca2010-08-19 05:56:385687 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065688
5689 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025690 SessionDependencies session_deps(
5691 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065692 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025693 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065694
5695 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285696 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5697 new CaptureGroupNameTransportSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135698 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345699 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025700 MockClientSocketPoolManager* mock_pool_manager =
5701 new MockClientSocketPoolManager;
5702 mock_pool_manager->SetTransportSocketPool(transport_conn_pool);
5703 mock_pool_manager->SetSSLSocketPool(ssl_conn_pool);
5704 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065705
5706 EXPECT_EQ(ERR_IO_PENDING,
5707 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185708 if (tests[i].ssl)
5709 EXPECT_EQ(tests[i].expected_group_name,
5710 ssl_conn_pool->last_group_name_received());
5711 else
5712 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285713 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065714 }
5715
[email protected]8e6441ca2010-08-19 05:56:385716 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065717}
5718
5719TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5720 const GroupNameTest tests[] = {
5721 {
5722 "http_proxy",
5723 "http://www.google.com/http_proxy_normal",
5724 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185725 false,
[email protected]2d731a32010-04-29 01:04:065726 },
5727
5728 // SSL Tests
5729 {
5730 "http_proxy",
5731 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025732 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185733 true,
[email protected]2d731a32010-04-29 01:04:065734 },
[email protected]af3490e2010-10-16 21:02:295735
[email protected]9faeded92010-04-29 20:03:055736 {
5737 "http_proxy",
5738 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025739 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185740 true,
[email protected]9faeded92010-04-29 20:03:055741 },
[email protected]2d731a32010-04-29 01:04:065742 };
5743
[email protected]8e6441ca2010-08-19 05:56:385744 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065745
5746 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025747 SessionDependencies session_deps(
5748 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065749 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025750 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065751
5752 HttpNetworkSessionPeer peer(session);
5753
[email protected]e60e47a2010-07-14 03:37:185754 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135755 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345756 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135757 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345758 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025759
5760 MockClientSocketPoolManager* mock_pool_manager =
5761 new MockClientSocketPoolManager;
5762 mock_pool_manager->SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
5763 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5764 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]2d731a32010-04-29 01:04:065765
5766 EXPECT_EQ(ERR_IO_PENDING,
5767 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185768 if (tests[i].ssl)
5769 EXPECT_EQ(tests[i].expected_group_name,
5770 ssl_conn_pool->last_group_name_received());
5771 else
5772 EXPECT_EQ(tests[i].expected_group_name,
5773 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065774 }
5775
[email protected]8e6441ca2010-08-19 05:56:385776 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065777}
5778
5779TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5780 const GroupNameTest tests[] = {
5781 {
5782 "socks4://socks_proxy:1080",
5783 "http://www.google.com/socks4_direct",
5784 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185785 false,
[email protected]2d731a32010-04-29 01:04:065786 },
5787 {
5788 "socks5://socks_proxy:1080",
5789 "http://www.google.com/socks5_direct",
5790 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185791 false,
[email protected]2d731a32010-04-29 01:04:065792 },
5793
5794 // SSL Tests
5795 {
5796 "socks4://socks_proxy:1080",
5797 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025798 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185799 true,
[email protected]2d731a32010-04-29 01:04:065800 },
5801 {
5802 "socks5://socks_proxy:1080",
5803 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025804 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185805 true,
[email protected]2d731a32010-04-29 01:04:065806 },
[email protected]af3490e2010-10-16 21:02:295807
[email protected]9faeded92010-04-29 20:03:055808 {
5809 "socks4://socks_proxy:1080",
5810 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025811 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185812 true,
[email protected]9faeded92010-04-29 20:03:055813 },
[email protected]04e5be32009-06-26 20:00:315814 };
5815
[email protected]8e6441ca2010-08-19 05:56:385816 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545817
[email protected]04e5be32009-06-26 20:00:315818 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025819 SessionDependencies session_deps(
5820 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065821 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025822 SetupSessionForGroupNameTests(&session_deps));
5823
[email protected]2d731a32010-04-29 01:04:065824 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315825
[email protected]e60e47a2010-07-14 03:37:185826 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135827 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345828 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]2431756e2010-09-29 20:26:135829 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345830 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]a42dbd142011-11-17 16:42:025831
5832 MockClientSocketPoolManager* mock_pool_manager =
5833 new MockClientSocketPoolManager;
5834 mock_pool_manager->SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
5835 mock_pool_manager->SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
5836 peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]04e5be32009-06-26 20:00:315837
[email protected]5695b8c2009-09-30 21:36:435838 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315839
[email protected]2d731a32010-04-29 01:04:065840 EXPECT_EQ(ERR_IO_PENDING,
5841 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185842 if (tests[i].ssl)
5843 EXPECT_EQ(tests[i].expected_group_name,
5844 ssl_conn_pool->last_group_name_received());
5845 else
5846 EXPECT_EQ(tests[i].expected_group_name,
5847 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315848 }
[email protected]2ff8b312010-04-26 22:20:545849
[email protected]8e6441ca2010-08-19 05:56:385850 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315851}
5852
[email protected]9172a982009-06-06 00:30:255853TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275854 HttpRequestInfo request;
5855 request.method = "GET";
5856 request.url = GURL("http://www.google.com/");
5857
[email protected]5c6a17e2009-06-10 00:54:545858 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005859 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325860
[email protected]69719062010-01-05 20:09:215861 // This simulates failure resolving all hostnames; that means we will fail
5862 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325863 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5864
[email protected]9172a982009-06-06 00:30:255865 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435866 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255867
[email protected]49639fa2011-12-20 23:22:415868 TestCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:255869
[email protected]49639fa2011-12-20 23:22:415870 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9172a982009-06-06 00:30:255871 EXPECT_EQ(ERR_IO_PENDING, rv);
5872
[email protected]9172a982009-06-06 00:30:255873 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015874 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255875}
5876
[email protected]685af592010-05-11 19:31:245877// Base test to make sure that when the load flags for a request specify to
5878// bypass the cache, the DNS cache is not used.
5879void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275880 // Issue a request, asking to bypass the cache(s).
5881 HttpRequestInfo request;
5882 request.method = "GET";
5883 request.load_flags = load_flags;
5884 request.url = GURL("http://www.google.com/");
5885
[email protected]3b9cca42009-06-16 01:08:285886 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325887
[email protected]a2c2fb92009-07-18 07:31:045888 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545889 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325890
[email protected]3b9cca42009-06-16 01:08:285891 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435892 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285893
[email protected]6e78dfb2011-07-28 21:34:475894 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285895 AddressList addrlist;
[email protected]aa22b242011-11-16 18:58:295896 TestCompletionCallback callback;
[email protected]94a0d3d92009-06-27 01:50:145897 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105898 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295899 callback.callback(), NULL, BoundNetLog());
[email protected]6e78dfb2011-07-28 21:34:475900 EXPECT_EQ(ERR_IO_PENDING, rv);
5901 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285902 EXPECT_EQ(OK, rv);
5903
5904 // Verify that it was added to host cache, by doing a subsequent async lookup
5905 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465906 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105907 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]aa22b242011-11-16 18:58:295908 callback.callback(), NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325909 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285910
5911 // Inject a failure the next time that "www.google.com" is resolved. This way
5912 // we can tell if the next lookup hit the cache, or the "network".
5913 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325914 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285915
5916 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5917 // first read -- this won't be reached as the host resolution will fail first.
5918 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395919 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595920 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285921
[email protected]3b9cca42009-06-16 01:08:285922 // Run the request.
[email protected]49639fa2011-12-20 23:22:415923 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285924 ASSERT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:415925 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285926
5927 // If we bypassed the cache, we would have gotten a failure while resolving
5928 // "www.google.com".
5929 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5930}
5931
[email protected]685af592010-05-11 19:31:245932// There are multiple load flags that should trigger the host cache bypass.
5933// Test each in isolation:
5934TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5935 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5936}
5937
5938TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5939 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5940}
5941
5942TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5943 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5944}
5945
[email protected]0877e3d2009-10-17 22:29:575946// Make sure we can handle an error when writing the request.
5947TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5948 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275949 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575950
5951 HttpRequestInfo request;
5952 request.method = "GET";
5953 request.url = GURL("http://www.foo.com/");
5954 request.load_flags = 0;
5955
5956 MockWrite write_failure[] = {
5957 MockWrite(true, ERR_CONNECTION_RESET),
5958 };
[email protected]31a2bfe2010-02-09 08:03:395959 StaticSocketDataProvider data(NULL, 0,
5960 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595961 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575962
[email protected]49639fa2011-12-20 23:22:415963 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575964
5965 scoped_ptr<HttpTransaction> trans(
5966 new HttpNetworkTransaction(CreateSession(&session_deps)));
5967
[email protected]49639fa2011-12-20 23:22:415968 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575969 EXPECT_EQ(ERR_IO_PENDING, rv);
5970
5971 rv = callback.WaitForResult();
5972 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5973}
5974
5975// Check that a connection closed after the start of the headers finishes ok.
5976TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5977 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275978 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575979
5980 HttpRequestInfo request;
5981 request.method = "GET";
5982 request.url = GURL("http://www.foo.com/");
5983 request.load_flags = 0;
5984
5985 MockRead data_reads[] = {
5986 MockRead("HTTP/1."),
5987 MockRead(false, OK),
5988 };
5989
[email protected]31a2bfe2010-02-09 08:03:395990 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595991 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575992
[email protected]49639fa2011-12-20 23:22:415993 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575994
5995 scoped_ptr<HttpTransaction> trans(
5996 new HttpNetworkTransaction(CreateSession(&session_deps)));
5997
[email protected]49639fa2011-12-20 23:22:415998 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575999 EXPECT_EQ(ERR_IO_PENDING, rv);
6000
6001 rv = callback.WaitForResult();
6002 EXPECT_EQ(OK, rv);
6003
6004 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506005 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:576006
6007 EXPECT_TRUE(response->headers != NULL);
6008 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6009
6010 std::string response_data;
6011 rv = ReadTransaction(trans.get(), &response_data);
6012 EXPECT_EQ(OK, rv);
6013 EXPECT_EQ("", response_data);
6014}
6015
6016// Make sure that a dropped connection while draining the body for auth
6017// restart does the right thing.
6018TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
6019 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:276020 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:576021
6022 HttpRequestInfo request;
6023 request.method = "GET";
6024 request.url = GURL("http://www.google.com/");
6025 request.load_flags = 0;
6026
6027 MockWrite data_writes1[] = {
6028 MockWrite("GET / HTTP/1.1\r\n"
6029 "Host: www.google.com\r\n"
6030 "Connection: keep-alive\r\n\r\n"),
6031 };
6032
6033 MockRead data_reads1[] = {
6034 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6035 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6036 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6037 MockRead("Content-Length: 14\r\n\r\n"),
6038 MockRead("Unauth"),
6039 MockRead(true, ERR_CONNECTION_RESET),
6040 };
6041
[email protected]31a2bfe2010-02-09 08:03:396042 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6043 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:596044 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:576045
6046 // After calling trans->RestartWithAuth(), this is the request we should
6047 // be issuing -- the final header line contains the credentials.
6048 MockWrite data_writes2[] = {
6049 MockWrite("GET / HTTP/1.1\r\n"
6050 "Host: www.google.com\r\n"
6051 "Connection: keep-alive\r\n"
6052 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6053 };
6054
6055 // Lastly, the server responds with the actual content.
6056 MockRead data_reads2[] = {
6057 MockRead("HTTP/1.1 200 OK\r\n"),
6058 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6059 MockRead("Content-Length: 100\r\n\r\n"),
6060 MockRead(false, OK),
6061 };
6062
[email protected]31a2bfe2010-02-09 08:03:396063 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6064 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:596065 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:576066
[email protected]49639fa2011-12-20 23:22:416067 TestCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:576068
[email protected]0b0bf032010-09-21 18:08:506069 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6070
[email protected]49639fa2011-12-20 23:22:416071 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576072 EXPECT_EQ(ERR_IO_PENDING, rv);
6073
6074 rv = callback1.WaitForResult();
6075 EXPECT_EQ(OK, rv);
6076
6077 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506078 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046079 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:576080
[email protected]49639fa2011-12-20 23:22:416081 TestCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:576082
[email protected]49639fa2011-12-20 23:22:416083 rv = trans->RestartWithAuth(
6084 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]0877e3d2009-10-17 22:29:576085 EXPECT_EQ(ERR_IO_PENDING, rv);
6086
6087 rv = callback2.WaitForResult();
6088 EXPECT_EQ(OK, rv);
6089
6090 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506091 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:576092 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6093 EXPECT_EQ(100, response->headers->GetContentLength());
6094}
6095
6096// Test HTTPS connections going through a proxy that sends extra data.
6097TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006098 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576099
6100 HttpRequestInfo request;
6101 request.method = "GET";
6102 request.url = GURL("https://www.google.com/");
6103 request.load_flags = 0;
6104
6105 MockRead proxy_reads[] = {
6106 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6107 MockRead(false, OK)
6108 };
6109
[email protected]31a2bfe2010-02-09 08:03:396110 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596111 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576112
[email protected]5ecc992a42009-11-11 01:41:596113 session_deps.socket_factory.AddSocketDataProvider(&data);
6114 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576115
[email protected]49639fa2011-12-20 23:22:416116 TestCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:576117
6118 session_deps.socket_factory.ResetNextMockIndexes();
6119
6120 scoped_ptr<HttpTransaction> trans(
6121 new HttpNetworkTransaction(CreateSession(&session_deps)));
6122
[email protected]49639fa2011-12-20 23:22:416123 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576124 EXPECT_EQ(ERR_IO_PENDING, rv);
6125
6126 rv = callback.WaitForResult();
6127 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6128}
6129
[email protected]e22e1362009-11-23 21:31:126130TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466131 HttpRequestInfo request;
6132 request.method = "GET";
6133 request.url = GURL("http://www.google.com/");
6134 request.load_flags = 0;
6135
[email protected]cb9bf6ca2011-01-28 13:15:276136 SessionDependencies session_deps;
6137 scoped_ptr<HttpTransaction> trans(
6138 new HttpNetworkTransaction(CreateSession(&session_deps)));
6139
[email protected]e22e1362009-11-23 21:31:126140 MockRead data_reads[] = {
6141 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6142 MockRead(false, OK),
6143 };
[email protected]9492e4a2010-02-24 00:58:466144
6145 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6146 session_deps.socket_factory.AddSocketDataProvider(&data);
6147
[email protected]49639fa2011-12-20 23:22:416148 TestCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:466149
[email protected]49639fa2011-12-20 23:22:416150 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466151 EXPECT_EQ(ERR_IO_PENDING, rv);
6152
6153 EXPECT_EQ(OK, callback.WaitForResult());
6154
6155 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506156 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:466157
6158 EXPECT_TRUE(response->headers != NULL);
6159 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6160
6161 std::string response_data;
6162 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f001bd6a2011-12-08 04:31:376163 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126164}
6165
[email protected]95d88ffe2010-02-04 21:25:336166TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336167 HttpRequestInfo request;
6168 request.method = "POST";
6169 request.url = GURL("http://www.google.com/upload");
6170 request.upload_data = new UploadData;
6171 request.load_flags = 0;
6172
[email protected]cb9bf6ca2011-01-28 13:15:276173 SessionDependencies session_deps;
6174 scoped_ptr<HttpTransaction> trans(
6175 new HttpNetworkTransaction(CreateSession(&session_deps)));
6176
[email protected]95d88ffe2010-02-04 21:25:336177 FilePath temp_file_path;
6178 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6179 const uint64 kFakeSize = 100000; // file is actually blank
6180
6181 std::vector<UploadData::Element> elements;
6182 UploadData::Element element;
6183 element.SetToFilePath(temp_file_path);
6184 element.SetContentLength(kFakeSize);
6185 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536186 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336187 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6188
6189 MockRead data_reads[] = {
6190 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6191 MockRead("hello world"),
6192 MockRead(false, OK),
6193 };
[email protected]31a2bfe2010-02-09 08:03:396194 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336195 session_deps.socket_factory.AddSocketDataProvider(&data);
6196
[email protected]49639fa2011-12-20 23:22:416197 TestCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:336198
[email protected]49639fa2011-12-20 23:22:416199 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336200 EXPECT_EQ(ERR_IO_PENDING, rv);
6201
6202 rv = callback.WaitForResult();
6203 EXPECT_EQ(OK, rv);
6204
6205 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506206 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:336207
6208 EXPECT_TRUE(response->headers != NULL);
6209 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6210
6211 std::string response_data;
6212 rv = ReadTransaction(trans.get(), &response_data);
6213 EXPECT_EQ(OK, rv);
6214 EXPECT_EQ("hello world", response_data);
6215
6216 file_util::Delete(temp_file_path, false);
6217}
6218
[email protected]6624b4622010-03-29 19:58:366219TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276220 HttpRequestInfo request;
6221 request.method = "POST";
6222 request.url = GURL("http://www.google.com/upload");
6223 request.upload_data = new UploadData;
6224 request.load_flags = 0;
6225
[email protected]6624b4622010-03-29 19:58:366226 // If we try to upload an unreadable file, the network stack should report
6227 // the file size as zero and upload zero bytes for that file.
6228 SessionDependencies session_deps;
6229 scoped_ptr<HttpTransaction> trans(
6230 new HttpNetworkTransaction(CreateSession(&session_deps)));
6231
6232 FilePath temp_file;
6233 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6234 std::string temp_file_content("Unreadable file.");
6235 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6236 temp_file_content.length()));
6237 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6238
[email protected]6624b4622010-03-29 19:58:366239 std::vector<UploadData::Element> elements;
6240 UploadData::Element element;
6241 element.SetToFilePath(temp_file);
6242 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536243 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366244
6245 MockRead data_reads[] = {
6246 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6247 MockRead(false, OK),
6248 };
6249 MockWrite data_writes[] = {
6250 MockWrite("POST /upload HTTP/1.1\r\n"
6251 "Host: www.google.com\r\n"
6252 "Connection: keep-alive\r\n"
6253 "Content-Length: 0\r\n\r\n"),
6254 MockWrite(false, OK),
6255 };
6256 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6257 arraysize(data_writes));
6258 session_deps.socket_factory.AddSocketDataProvider(&data);
6259
[email protected]49639fa2011-12-20 23:22:416260 TestCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:366261
[email protected]49639fa2011-12-20 23:22:416262 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366263 EXPECT_EQ(ERR_IO_PENDING, rv);
6264
6265 rv = callback.WaitForResult();
6266 EXPECT_EQ(OK, rv);
6267
6268 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506269 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366270 EXPECT_TRUE(response->headers != NULL);
6271 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6272
6273 file_util::Delete(temp_file, false);
6274}
6275
6276TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276277 HttpRequestInfo request;
6278 request.method = "POST";
6279 request.url = GURL("http://www.google.com/upload");
6280 request.upload_data = new UploadData;
6281 request.load_flags = 0;
6282
[email protected]6624b4622010-03-29 19:58:366283 SessionDependencies session_deps;
6284 scoped_ptr<HttpTransaction> trans(
6285 new HttpNetworkTransaction(CreateSession(&session_deps)));
6286
6287 FilePath temp_file;
6288 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6289 std::string temp_file_contents("Unreadable file.");
6290 std::string unreadable_contents(temp_file_contents.length(), '\0');
6291 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6292 temp_file_contents.length()));
6293
[email protected]6624b4622010-03-29 19:58:366294 std::vector<UploadData::Element> elements;
6295 UploadData::Element element;
6296 element.SetToFilePath(temp_file);
6297 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536298 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366299
6300 MockRead data_reads[] = {
6301 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6302 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6303 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6304
6305 MockRead("HTTP/1.1 200 OK\r\n"),
6306 MockRead("Content-Length: 0\r\n\r\n"),
6307 MockRead(false, OK),
6308 };
6309 MockWrite data_writes[] = {
6310 MockWrite("POST /upload HTTP/1.1\r\n"
6311 "Host: www.google.com\r\n"
6312 "Connection: keep-alive\r\n"
6313 "Content-Length: 16\r\n\r\n"),
6314 MockWrite(false, temp_file_contents.c_str()),
6315
6316 MockWrite("POST /upload HTTP/1.1\r\n"
6317 "Host: www.google.com\r\n"
6318 "Connection: keep-alive\r\n"
6319 "Content-Length: 16\r\n"
6320 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6321 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6322 MockWrite(false, OK),
6323 };
6324 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6325 arraysize(data_writes));
6326 session_deps.socket_factory.AddSocketDataProvider(&data);
6327
[email protected]49639fa2011-12-20 23:22:416328 TestCompletionCallback callback1;
[email protected]6624b4622010-03-29 19:58:366329
[email protected]49639fa2011-12-20 23:22:416330 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366331 EXPECT_EQ(ERR_IO_PENDING, rv);
6332
6333 rv = callback1.WaitForResult();
6334 EXPECT_EQ(OK, rv);
6335
6336 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:046337 ASSERT_TRUE(response != NULL);
6338 ASSERT_TRUE(response->headers != NULL);
[email protected]6624b4622010-03-29 19:58:366339 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
[email protected]79cb5c12011-09-12 13:12:046340 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]6624b4622010-03-29 19:58:366341
6342 // Now make the file unreadable and try again.
6343 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6344
[email protected]49639fa2011-12-20 23:22:416345 TestCompletionCallback callback2;
[email protected]6624b4622010-03-29 19:58:366346
[email protected]49639fa2011-12-20 23:22:416347 rv = trans->RestartWithAuth(
6348 AuthCredentials(kFoo, kBar), callback2.callback());
[email protected]6624b4622010-03-29 19:58:366349 EXPECT_EQ(ERR_IO_PENDING, rv);
6350
6351 rv = callback2.WaitForResult();
6352 EXPECT_EQ(OK, rv);
6353
6354 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506355 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366356 EXPECT_TRUE(response->headers != NULL);
6357 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6358 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6359
6360 file_util::Delete(temp_file, false);
6361}
6362
[email protected]aeefc9e82010-02-19 16:18:276363// Tests that changes to Auth realms are treated like auth rejections.
6364TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6365 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276366
6367 HttpRequestInfo request;
6368 request.method = "GET";
6369 request.url = GURL("http://www.google.com/");
6370 request.load_flags = 0;
6371
6372 // First transaction will request a resource and receive a Basic challenge
6373 // with realm="first_realm".
6374 MockWrite data_writes1[] = {
6375 MockWrite("GET / HTTP/1.1\r\n"
6376 "Host: www.google.com\r\n"
6377 "Connection: keep-alive\r\n"
6378 "\r\n"),
6379 };
6380 MockRead data_reads1[] = {
6381 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6382 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6383 "\r\n"),
6384 };
6385
6386 // After calling trans->RestartWithAuth(), provide an Authentication header
6387 // for first_realm. The server will reject and provide a challenge with
6388 // second_realm.
6389 MockWrite data_writes2[] = {
6390 MockWrite("GET / HTTP/1.1\r\n"
6391 "Host: www.google.com\r\n"
6392 "Connection: keep-alive\r\n"
6393 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6394 "\r\n"),
6395 };
6396 MockRead data_reads2[] = {
6397 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6398 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6399 "\r\n"),
6400 };
6401
6402 // This again fails, and goes back to first_realm. Make sure that the
6403 // entry is removed from cache.
6404 MockWrite data_writes3[] = {
6405 MockWrite("GET / HTTP/1.1\r\n"
6406 "Host: www.google.com\r\n"
6407 "Connection: keep-alive\r\n"
6408 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6409 "\r\n"),
6410 };
6411 MockRead data_reads3[] = {
6412 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6413 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6414 "\r\n"),
6415 };
6416
6417 // Try one last time (with the correct password) and get the resource.
6418 MockWrite data_writes4[] = {
6419 MockWrite("GET / HTTP/1.1\r\n"
6420 "Host: www.google.com\r\n"
6421 "Connection: keep-alive\r\n"
6422 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6423 "\r\n"),
6424 };
6425 MockRead data_reads4[] = {
6426 MockRead("HTTP/1.1 200 OK\r\n"
6427 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506428 "Content-Length: 5\r\n"
6429 "\r\n"
6430 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276431 };
6432
6433 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6434 data_writes1, arraysize(data_writes1));
6435 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6436 data_writes2, arraysize(data_writes2));
6437 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6438 data_writes3, arraysize(data_writes3));
6439 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6440 data_writes4, arraysize(data_writes4));
6441 session_deps.socket_factory.AddSocketDataProvider(&data1);
6442 session_deps.socket_factory.AddSocketDataProvider(&data2);
6443 session_deps.socket_factory.AddSocketDataProvider(&data3);
6444 session_deps.socket_factory.AddSocketDataProvider(&data4);
6445
[email protected]49639fa2011-12-20 23:22:416446 TestCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:276447
[email protected]0b0bf032010-09-21 18:08:506448 scoped_ptr<HttpTransaction> trans(
6449 new HttpNetworkTransaction(CreateSession(&session_deps)));
6450
[email protected]aeefc9e82010-02-19 16:18:276451 // Issue the first request with Authorize headers. There should be a
6452 // password prompt for first_realm waiting to be filled in after the
6453 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416454 int rv = trans->Start(&request, callback1.callback(), BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276455 EXPECT_EQ(ERR_IO_PENDING, rv);
6456 rv = callback1.WaitForResult();
6457 EXPECT_EQ(OK, rv);
6458 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506459 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046460 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6461 ASSERT_FALSE(challenge == NULL);
6462 EXPECT_FALSE(challenge->is_proxy);
6463 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6464 EXPECT_EQ("first_realm", challenge->realm);
6465 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276466
6467 // Issue the second request with an incorrect password. There should be a
6468 // password prompt for second_realm waiting to be filled in after the
6469 // transaction completes.
[email protected]49639fa2011-12-20 23:22:416470 TestCompletionCallback callback2;
6471 rv = trans->RestartWithAuth(
6472 AuthCredentials(kFirst, kBaz), callback2.callback());
[email protected]aeefc9e82010-02-19 16:18:276473 EXPECT_EQ(ERR_IO_PENDING, rv);
6474 rv = callback2.WaitForResult();
6475 EXPECT_EQ(OK, rv);
6476 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506477 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046478 challenge = response->auth_challenge.get();
6479 ASSERT_FALSE(challenge == NULL);
6480 EXPECT_FALSE(challenge->is_proxy);
6481 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6482 EXPECT_EQ("second_realm", challenge->realm);
6483 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276484
6485 // Issue the third request with another incorrect password. There should be
6486 // a password prompt for first_realm waiting to be filled in. If the password
6487 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6488 // first_realm was not correctly removed.
[email protected]49639fa2011-12-20 23:22:416489 TestCompletionCallback callback3;
6490 rv = trans->RestartWithAuth(
6491 AuthCredentials(kSecond, kFou), callback3.callback());
[email protected]aeefc9e82010-02-19 16:18:276492 EXPECT_EQ(ERR_IO_PENDING, rv);
6493 rv = callback3.WaitForResult();
6494 EXPECT_EQ(OK, rv);
6495 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506496 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046497 challenge = response->auth_challenge.get();
6498 ASSERT_FALSE(challenge == NULL);
6499 EXPECT_FALSE(challenge->is_proxy);
6500 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6501 EXPECT_EQ("first_realm", challenge->realm);
6502 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276503
6504 // Issue the fourth request with the correct password and username.
[email protected]49639fa2011-12-20 23:22:416505 TestCompletionCallback callback4;
6506 rv = trans->RestartWithAuth(
6507 AuthCredentials(kFirst, kBar), callback4.callback());
[email protected]aeefc9e82010-02-19 16:18:276508 EXPECT_EQ(ERR_IO_PENDING, rv);
6509 rv = callback4.WaitForResult();
6510 EXPECT_EQ(OK, rv);
6511 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506512 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:276513 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6514}
6515
[email protected]564b4912010-03-09 16:30:426516TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]5285d972011-10-18 18:56:346517 HttpStreamFactory::set_next_protos(MakeNextProtos("foo", "bar", NULL));
[email protected]8e6441ca2010-08-19 05:56:386518 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426519
[email protected]564b4912010-03-09 16:30:426520 SessionDependencies session_deps;
6521
6522 MockRead data_reads[] = {
6523 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356524 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426525 MockRead("hello world"),
6526 MockRead(false, OK),
6527 };
6528
6529 HttpRequestInfo request;
6530 request.method = "GET";
6531 request.url = GURL("http://www.google.com/");
6532 request.load_flags = 0;
6533
6534 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6535
6536 session_deps.socket_factory.AddSocketDataProvider(&data);
6537
[email protected]49639fa2011-12-20 23:22:416538 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426539
6540 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6541 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6542
[email protected]49639fa2011-12-20 23:22:416543 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426544 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536545
[email protected]2fbaecf22010-07-22 22:20:356546 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]17291a022011-10-10 07:32:536547 const HttpServerProperties& http_server_properties =
6548 *session->http_server_properties();
[email protected]564b4912010-03-09 16:30:426549 EXPECT_FALSE(
[email protected]17291a022011-10-10 07:32:536550 http_server_properties.HasAlternateProtocol(http_host_port_pair));
[email protected]564b4912010-03-09 16:30:426551
6552 EXPECT_EQ(OK, callback.WaitForResult());
6553
6554 const HttpResponseInfo* response = trans->GetResponseInfo();
6555 ASSERT_TRUE(response != NULL);
6556 ASSERT_TRUE(response->headers != NULL);
6557 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536558 EXPECT_FALSE(response->was_fetched_via_spdy);
6559 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426560
6561 std::string response_data;
6562 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6563 EXPECT_EQ("hello world", response_data);
6564
[email protected]17291a022011-10-10 07:32:536565 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6566 const PortAlternateProtocolPair alternate =
6567 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6568 PortAlternateProtocolPair expected_alternate;
[email protected]564b4912010-03-09 16:30:426569 expected_alternate.port = 443;
[email protected]1ad77dc2012-01-27 03:51:206570 expected_alternate.protocol = NPN_SPDY_21;
[email protected]564b4912010-03-09 16:30:426571 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426572
[email protected]8e6441ca2010-08-19 05:56:386573 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]5285d972011-10-18 18:56:346574 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]564b4912010-03-09 16:30:426575}
6576
[email protected]8b95ed62011-03-18 18:12:036577TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386578 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426579 SessionDependencies session_deps;
6580
6581 HttpRequestInfo request;
6582 request.method = "GET";
6583 request.url = GURL("http://www.google.com/");
6584 request.load_flags = 0;
6585
6586 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6587 StaticSocketDataProvider first_data;
6588 first_data.set_connect_data(mock_connect);
6589 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6590
6591 MockRead data_reads[] = {
6592 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6593 MockRead("hello world"),
6594 MockRead(true, OK),
6595 };
6596 StaticSocketDataProvider second_data(
6597 data_reads, arraysize(data_reads), NULL, 0);
6598 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6599
[email protected]564b4912010-03-09 16:30:426600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6601
[email protected]17291a022011-10-10 07:32:536602 HttpServerProperties* http_server_properties =
6603 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116604 // Port must be < 1024, or the header will be ignored (since initial port was
6605 // port 80 (another restricted port).
[email protected]17291a022011-10-10 07:32:536606 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116607 HostPortPair::FromURL(request.url),
6608 666 /* port is ignored by MockConnect anyway */,
[email protected]1ad77dc2012-01-27 03:51:206609 NPN_SPDY_21);
[email protected]564b4912010-03-09 16:30:426610
6611 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416612 TestCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426613
[email protected]49639fa2011-12-20 23:22:416614 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]564b4912010-03-09 16:30:426615 EXPECT_EQ(ERR_IO_PENDING, rv);
6616 EXPECT_EQ(OK, callback.WaitForResult());
6617
6618 const HttpResponseInfo* response = trans->GetResponseInfo();
6619 ASSERT_TRUE(response != NULL);
6620 ASSERT_TRUE(response->headers != NULL);
6621 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6622
6623 std::string response_data;
6624 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6625 EXPECT_EQ("hello world", response_data);
6626
[email protected]17291a022011-10-10 07:32:536627 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116628 HostPortPair::FromURL(request.url)));
[email protected]17291a022011-10-10 07:32:536629 const PortAlternateProtocolPair alternate =
6630 http_server_properties->GetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116631 HostPortPair::FromURL(request.url));
[email protected]17291a022011-10-10 07:32:536632 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386633 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426634}
6635
[email protected]3912662a32011-10-04 00:51:116636TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6637 // Ensure that we're not allowed to redirect traffic via an alternate
6638 // protocol to an unrestricted (port >= 1024) when the original traffic was
6639 // on a restricted port (port < 1024). Ensure that we can redirect in all
6640 // other cases.
6641 HttpStreamFactory::set_use_alternate_protocols(true);
6642 SessionDependencies session_deps;
6643
6644 HttpRequestInfo restricted_port_request;
6645 restricted_port_request.method = "GET";
6646 restricted_port_request.url = GURL("http://www.google.com:1023/");
6647 restricted_port_request.load_flags = 0;
6648
6649 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6650 StaticSocketDataProvider first_data;
6651 first_data.set_connect_data(mock_connect);
6652 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6653
6654 MockRead data_reads[] = {
6655 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6656 MockRead("hello world"),
6657 MockRead(true, OK),
6658 };
6659 StaticSocketDataProvider second_data(
6660 data_reads, arraysize(data_reads), NULL, 0);
6661 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6662
6663 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6664
[email protected]17291a022011-10-10 07:32:536665 HttpServerProperties* http_server_properties =
6666 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116667 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536668 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116669 HostPortPair::FromURL(restricted_port_request.url),
6670 kUnrestrictedAlternatePort,
[email protected]1ad77dc2012-01-27 03:51:206671 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116672
6673 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416674 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116675
[email protected]49639fa2011-12-20 23:22:416676 int rv = trans->Start(
6677 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116678 EXPECT_EQ(ERR_IO_PENDING, rv);
6679 // Invalid change to unrestricted port should fail.
6680 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6681
6682 HttpStreamFactory::set_use_alternate_protocols(false);
6683}
6684
6685TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6686 // Ensure that we're not allowed to redirect traffic via an alternate
6687 // protocol to an unrestricted (port >= 1024) when the original traffic was
6688 // on a restricted port (port < 1024). Ensure that we can redirect in all
6689 // other cases.
6690 HttpStreamFactory::set_use_alternate_protocols(true);
6691 SessionDependencies session_deps;
6692
6693 HttpRequestInfo restricted_port_request;
6694 restricted_port_request.method = "GET";
6695 restricted_port_request.url = GURL("http://www.google.com:1023/");
6696 restricted_port_request.load_flags = 0;
6697
6698 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6699 StaticSocketDataProvider first_data;
6700 first_data.set_connect_data(mock_connect);
6701 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6702
6703 MockRead data_reads[] = {
6704 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6705 MockRead("hello world"),
6706 MockRead(true, OK),
6707 };
6708 StaticSocketDataProvider second_data(
6709 data_reads, arraysize(data_reads), NULL, 0);
6710 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6711
6712 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6713
[email protected]17291a022011-10-10 07:32:536714 HttpServerProperties* http_server_properties =
6715 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116716 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536717 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116718 HostPortPair::FromURL(restricted_port_request.url),
6719 kRestrictedAlternatePort,
[email protected]1ad77dc2012-01-27 03:51:206720 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116721
6722 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416723 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116724
[email protected]49639fa2011-12-20 23:22:416725 int rv = trans->Start(
6726 &restricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116727 EXPECT_EQ(ERR_IO_PENDING, rv);
6728 // Valid change to restricted port should pass.
6729 EXPECT_EQ(OK, callback.WaitForResult());
6730
6731 HttpStreamFactory::set_use_alternate_protocols(false);
6732}
6733
6734TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6735 // Ensure that we're not allowed to redirect traffic via an alternate
6736 // protocol to an unrestricted (port >= 1024) when the original traffic was
6737 // on a restricted port (port < 1024). Ensure that we can redirect in all
6738 // other cases.
6739 HttpStreamFactory::set_use_alternate_protocols(true);
6740 SessionDependencies session_deps;
6741
6742 HttpRequestInfo unrestricted_port_request;
6743 unrestricted_port_request.method = "GET";
6744 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6745 unrestricted_port_request.load_flags = 0;
6746
6747 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6748 StaticSocketDataProvider first_data;
6749 first_data.set_connect_data(mock_connect);
6750 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6751
6752 MockRead data_reads[] = {
6753 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6754 MockRead("hello world"),
6755 MockRead(true, OK),
6756 };
6757 StaticSocketDataProvider second_data(
6758 data_reads, arraysize(data_reads), NULL, 0);
6759 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6760
6761 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6762
[email protected]17291a022011-10-10 07:32:536763 HttpServerProperties* http_server_properties =
6764 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116765 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536766 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116767 HostPortPair::FromURL(unrestricted_port_request.url),
6768 kRestrictedAlternatePort,
[email protected]1ad77dc2012-01-27 03:51:206769 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116770
6771 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416772 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116773
[email protected]49639fa2011-12-20 23:22:416774 int rv = trans->Start(
6775 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116776 EXPECT_EQ(ERR_IO_PENDING, rv);
6777 // Valid change to restricted port should pass.
6778 EXPECT_EQ(OK, callback.WaitForResult());
6779
6780 HttpStreamFactory::set_use_alternate_protocols(false);
6781}
6782
6783TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6784 // Ensure that we're not allowed to redirect traffic via an alternate
6785 // protocol to an unrestricted (port >= 1024) when the original traffic was
6786 // on a restricted port (port < 1024). Ensure that we can redirect in all
6787 // other cases.
6788 HttpStreamFactory::set_use_alternate_protocols(true);
6789 SessionDependencies session_deps;
6790
6791 HttpRequestInfo unrestricted_port_request;
6792 unrestricted_port_request.method = "GET";
6793 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6794 unrestricted_port_request.load_flags = 0;
6795
6796 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6797 StaticSocketDataProvider first_data;
6798 first_data.set_connect_data(mock_connect);
6799 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6800
6801 MockRead data_reads[] = {
6802 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6803 MockRead("hello world"),
6804 MockRead(true, OK),
6805 };
6806 StaticSocketDataProvider second_data(
6807 data_reads, arraysize(data_reads), NULL, 0);
6808 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6809
6810 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6811
[email protected]17291a022011-10-10 07:32:536812 HttpServerProperties* http_server_properties =
6813 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116814 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536815 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116816 HostPortPair::FromURL(unrestricted_port_request.url),
6817 kUnrestrictedAlternatePort,
[email protected]1ad77dc2012-01-27 03:51:206818 NPN_SPDY_21);
[email protected]3912662a32011-10-04 00:51:116819
6820 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:416821 TestCompletionCallback callback;
[email protected]3912662a32011-10-04 00:51:116822
[email protected]49639fa2011-12-20 23:22:416823 int rv = trans->Start(
6824 &unrestricted_port_request, callback.callback(), BoundNetLog());
[email protected]3912662a32011-10-04 00:51:116825 EXPECT_EQ(ERR_IO_PENDING, rv);
6826 // Valid change to an unrestricted port should pass.
6827 EXPECT_EQ(OK, callback.WaitForResult());
6828
6829 HttpStreamFactory::set_use_alternate_protocols(false);
6830}
6831
[email protected]eb6234e2012-01-19 01:50:026832TEST_F(HttpNetworkTransactionTest, AlternateProtocolUnsafeBlocked) {
6833 // Ensure that we're not allowed to redirect traffic via an alternate
6834 // protocol to an unsafe port, and that we resume the second
6835 // HttpStreamFactoryImpl::Job once the alternate protocol request fails.
6836 HttpStreamFactory::set_use_alternate_protocols(true);
6837 SessionDependencies session_deps;
6838
6839 HttpRequestInfo request;
6840 request.method = "GET";
6841 request.url = GURL("http://www.google.com/");
6842 request.load_flags = 0;
6843
6844 // The alternate protocol request will error out before we attempt to connect,
6845 // so only the standard HTTP request will try to connect.
6846 MockRead data_reads[] = {
6847 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6848 MockRead("hello world"),
6849 MockRead(true, OK),
6850 };
6851 StaticSocketDataProvider data(
6852 data_reads, arraysize(data_reads), NULL, 0);
6853 session_deps.socket_factory.AddSocketDataProvider(&data);
6854
6855 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6856
6857 HttpServerProperties* http_server_properties =
6858 session->http_server_properties();
6859 const int kUnsafePort = 7;
6860 http_server_properties->SetAlternateProtocol(
6861 HostPortPair::FromURL(request.url),
6862 kUnsafePort,
6863 NPN_SPDY_2);
6864
6865 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6866 TestCompletionCallback callback;
6867
6868 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
6869 EXPECT_EQ(ERR_IO_PENDING, rv);
6870 // The HTTP request should succeed.
6871 EXPECT_EQ(OK, callback.WaitForResult());
6872
6873 // Disable alternate protocol before the asserts.
6874 HttpStreamFactory::set_use_alternate_protocols(false);
6875
6876 const HttpResponseInfo* response = trans->GetResponseInfo();
6877 ASSERT_TRUE(response != NULL);
6878 ASSERT_TRUE(response->headers != NULL);
6879 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6880
6881 std::string response_data;
6882 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6883 EXPECT_EQ("hello world", response_data);
6884}
6885
[email protected]2ff8b312010-04-26 22:20:546886TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386887 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346888 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:546889 SessionDependencies session_deps;
6890
6891 HttpRequestInfo request;
6892 request.method = "GET";
6893 request.url = GURL("http://www.google.com/");
6894 request.load_flags = 0;
6895
6896 MockRead data_reads[] = {
6897 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356898 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546899 MockRead("hello world"),
6900 MockRead(true, OK),
6901 };
6902
6903 StaticSocketDataProvider first_transaction(
6904 data_reads, arraysize(data_reads), NULL, 0);
6905 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6906
6907 SSLSocketDataProvider ssl(true, OK);
6908 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:206909 ssl.next_proto = "spdy/2.1";
[email protected]65041fa2010-05-21 06:56:536910 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:206911 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2ff8b312010-04-26 22:20:546912 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6913
[email protected]2bd93022010-07-17 00:58:446914 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136915 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546916
[email protected]2bd93022010-07-17 00:58:446917 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6918 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546919 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136920 CreateMockRead(*resp),
6921 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546922 MockRead(true, 0, 0),
6923 };
6924
[email protected]a1595312012-01-22 03:25:046925 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:546926 new DelayedSocketData(
6927 1, // wait for one write to finish before reading.
6928 spdy_reads, arraysize(spdy_reads),
6929 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:046930 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:546931
[email protected]2d6728692011-03-12 01:39:556932 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6933 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6934 NULL, 0, NULL, 0);
6935 hanging_non_alternate_protocol_socket.set_connect_data(
6936 never_finishing_connect);
6937 session_deps.socket_factory.AddSocketDataProvider(
6938 &hanging_non_alternate_protocol_socket);
6939
[email protected]49639fa2011-12-20 23:22:416940 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:546941
6942 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6943 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6944
[email protected]49639fa2011-12-20 23:22:416945 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546946 EXPECT_EQ(ERR_IO_PENDING, rv);
6947 EXPECT_EQ(OK, callback.WaitForResult());
6948
6949 const HttpResponseInfo* response = trans->GetResponseInfo();
6950 ASSERT_TRUE(response != NULL);
6951 ASSERT_TRUE(response->headers != NULL);
6952 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6953
6954 std::string response_data;
6955 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6956 EXPECT_EQ("hello world", response_data);
6957
6958 trans.reset(new HttpNetworkTransaction(session));
6959
[email protected]49639fa2011-12-20 23:22:416960 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546961 EXPECT_EQ(ERR_IO_PENDING, rv);
6962 EXPECT_EQ(OK, callback.WaitForResult());
6963
6964 response = trans->GetResponseInfo();
6965 ASSERT_TRUE(response != NULL);
6966 ASSERT_TRUE(response->headers != NULL);
6967 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536968 EXPECT_TRUE(response->was_fetched_via_spdy);
6969 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546970
6971 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6972 EXPECT_EQ("hello!", response_data);
6973
[email protected]5285d972011-10-18 18:56:346974 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:386975 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546976}
6977
[email protected]2d6728692011-03-12 01:39:556978TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6979 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346980 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556981 SessionDependencies session_deps;
6982
6983 HttpRequestInfo request;
6984 request.method = "GET";
6985 request.url = GURL("http://www.google.com/");
6986 request.load_flags = 0;
6987
6988 MockRead data_reads[] = {
6989 MockRead("HTTP/1.1 200 OK\r\n"),
6990 MockRead(kAlternateProtocolHttpHeader),
6991 MockRead("hello world"),
6992 MockRead(true, OK),
6993 };
6994
6995 StaticSocketDataProvider first_transaction(
6996 data_reads, arraysize(data_reads), NULL, 0);
6997 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6998 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6999
7000 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7001 StaticSocketDataProvider hanging_socket(
7002 NULL, 0, NULL, 0);
7003 hanging_socket.set_connect_data(never_finishing_connect);
7004 // Socket 2 and 3 are the hanging Alternate-Protocol and
7005 // non-Alternate-Protocol jobs from the 2nd transaction.
7006 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
7007 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
7008
7009 SSLSocketDataProvider ssl(true, OK);
7010 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:207011 ssl.next_proto = "spdy/2.1";
[email protected]2d6728692011-03-12 01:39:557012 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:207013 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2d6728692011-03-12 01:39:557014 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7015
7016 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7017 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
7018 MockWrite spdy_writes[] = {
7019 CreateMockWrite(*req1),
7020 CreateMockWrite(*req2),
7021 };
7022 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
7023 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
7024 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
7025 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
7026 MockRead spdy_reads[] = {
7027 CreateMockRead(*resp1),
7028 CreateMockRead(*data1),
7029 CreateMockRead(*resp2),
7030 CreateMockRead(*data2),
7031 MockRead(true, 0, 0),
7032 };
7033
[email protected]a1595312012-01-22 03:25:047034 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2d6728692011-03-12 01:39:557035 new DelayedSocketData(
7036 2, // wait for writes to finish before reading.
7037 spdy_reads, arraysize(spdy_reads),
7038 spdy_writes, arraysize(spdy_writes)));
7039 // Socket 4 is the successful Alternate-Protocol for transaction 3.
[email protected]a1595312012-01-22 03:25:047040 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2d6728692011-03-12 01:39:557041
7042 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
7043 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
7044
7045 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]49639fa2011-12-20 23:22:417046 TestCompletionCallback callback1;
[email protected]2d6728692011-03-12 01:39:557047 HttpNetworkTransaction trans1(session);
7048
[email protected]49639fa2011-12-20 23:22:417049 int rv = trans1.Start(&request, callback1.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557050 EXPECT_EQ(ERR_IO_PENDING, rv);
7051 EXPECT_EQ(OK, callback1.WaitForResult());
7052
7053 const HttpResponseInfo* response = trans1.GetResponseInfo();
7054 ASSERT_TRUE(response != NULL);
7055 ASSERT_TRUE(response->headers != NULL);
7056 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7057
7058 std::string response_data;
7059 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
7060 EXPECT_EQ("hello world", response_data);
7061
[email protected]49639fa2011-12-20 23:22:417062 TestCompletionCallback callback2;
[email protected]2d6728692011-03-12 01:39:557063 HttpNetworkTransaction trans2(session);
[email protected]49639fa2011-12-20 23:22:417064 rv = trans2.Start(&request, callback2.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557065 EXPECT_EQ(ERR_IO_PENDING, rv);
7066
[email protected]49639fa2011-12-20 23:22:417067 TestCompletionCallback callback3;
[email protected]2d6728692011-03-12 01:39:557068 HttpNetworkTransaction trans3(session);
[email protected]49639fa2011-12-20 23:22:417069 rv = trans3.Start(&request, callback3.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557070 EXPECT_EQ(ERR_IO_PENDING, rv);
7071
7072 EXPECT_EQ(OK, callback2.WaitForResult());
7073 EXPECT_EQ(OK, callback3.WaitForResult());
7074
7075 response = trans2.GetResponseInfo();
7076 ASSERT_TRUE(response != NULL);
7077 ASSERT_TRUE(response->headers != NULL);
7078 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7079 EXPECT_TRUE(response->was_fetched_via_spdy);
7080 EXPECT_TRUE(response->was_npn_negotiated);
7081 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
7082 EXPECT_EQ("hello!", response_data);
7083
7084 response = trans3.GetResponseInfo();
7085 ASSERT_TRUE(response != NULL);
7086 ASSERT_TRUE(response->headers != NULL);
7087 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7088 EXPECT_TRUE(response->was_fetched_via_spdy);
7089 EXPECT_TRUE(response->was_npn_negotiated);
7090 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
7091 EXPECT_EQ("hello!", response_data);
7092
[email protected]5285d972011-10-18 18:56:347093 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557094 HttpStreamFactory::set_use_alternate_protocols(false);
7095}
7096
7097TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
7098 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347099 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:557100 SessionDependencies session_deps;
7101
7102 HttpRequestInfo request;
7103 request.method = "GET";
7104 request.url = GURL("http://www.google.com/");
7105 request.load_flags = 0;
7106
7107 MockRead data_reads[] = {
7108 MockRead("HTTP/1.1 200 OK\r\n"),
7109 MockRead(kAlternateProtocolHttpHeader),
7110 MockRead("hello world"),
7111 MockRead(true, OK),
7112 };
7113
7114 StaticSocketDataProvider first_transaction(
7115 data_reads, arraysize(data_reads), NULL, 0);
7116 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7117
7118 SSLSocketDataProvider ssl(true, OK);
7119 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:207120 ssl.next_proto = "spdy/2.1";
[email protected]2d6728692011-03-12 01:39:557121 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:207122 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2d6728692011-03-12 01:39:557123 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7124
7125 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7126 StaticSocketDataProvider hanging_alternate_protocol_socket(
7127 NULL, 0, NULL, 0);
7128 hanging_alternate_protocol_socket.set_connect_data(
7129 never_finishing_connect);
7130 session_deps.socket_factory.AddSocketDataProvider(
7131 &hanging_alternate_protocol_socket);
7132
7133 // 2nd request is just a copy of the first one, over HTTP again.
7134 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7135
[email protected]49639fa2011-12-20 23:22:417136 TestCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:557137
7138 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7139 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7140
[email protected]49639fa2011-12-20 23:22:417141 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557142 EXPECT_EQ(ERR_IO_PENDING, rv);
7143 EXPECT_EQ(OK, callback.WaitForResult());
7144
7145 const HttpResponseInfo* response = trans->GetResponseInfo();
7146 ASSERT_TRUE(response != NULL);
7147 ASSERT_TRUE(response->headers != NULL);
7148 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7149
7150 std::string response_data;
7151 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7152 EXPECT_EQ("hello world", response_data);
7153
7154 trans.reset(new HttpNetworkTransaction(session));
7155
[email protected]49639fa2011-12-20 23:22:417156 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2d6728692011-03-12 01:39:557157 EXPECT_EQ(ERR_IO_PENDING, rv);
7158 EXPECT_EQ(OK, callback.WaitForResult());
7159
7160 response = trans->GetResponseInfo();
7161 ASSERT_TRUE(response != NULL);
7162 ASSERT_TRUE(response->headers != NULL);
7163 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7164 EXPECT_FALSE(response->was_fetched_via_spdy);
7165 EXPECT_FALSE(response->was_npn_negotiated);
7166
7167 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7168 EXPECT_EQ("hello world", response_data);
7169
[email protected]5285d972011-10-18 18:56:347170 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557171 HttpStreamFactory::set_use_alternate_protocols(false);
7172}
7173
[email protected]631f1322010-04-30 17:59:117174class CapturingProxyResolver : public ProxyResolver {
7175 public:
7176 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7177 virtual ~CapturingProxyResolver() {}
7178
7179 virtual int GetProxyForURL(const GURL& url,
7180 ProxyInfo* results,
[email protected]235786812011-12-20 02:15:317181 const CompletionCallback& callback,
[email protected]631f1322010-04-30 17:59:117182 RequestHandle* request,
7183 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:407184 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7185 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:427186 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:117187 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:427188 return OK;
[email protected]631f1322010-04-30 17:59:117189 }
7190
7191 virtual void CancelRequest(RequestHandle request) {
7192 NOTREACHED();
7193 }
7194
[email protected]f2c971f2011-11-08 00:33:177195 virtual LoadState GetLoadState(RequestHandle request) const OVERRIDE {
7196 NOTREACHED();
7197 return LOAD_STATE_IDLE;
7198 }
7199
7200 virtual LoadState GetLoadStateThreadSafe(
7201 RequestHandle request) const OVERRIDE {
7202 NOTREACHED();
7203 return LOAD_STATE_IDLE;
7204 }
7205
[email protected]1e605472010-12-16 21:41:407206 virtual void CancelSetPacScript() {
7207 NOTREACHED();
7208 }
7209
[email protected]24476402010-07-20 20:55:177210 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]235786812011-12-20 02:15:317211 const CompletionCallback& /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:427212 return OK;
[email protected]631f1322010-04-30 17:59:117213 }
7214
[email protected]24476402010-07-20 20:55:177215 const std::vector<GURL>& resolved() const { return resolved_; }
7216
7217 private:
[email protected]631f1322010-04-30 17:59:117218 std::vector<GURL> resolved_;
7219
7220 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7221};
7222
[email protected]631f1322010-04-30 17:59:117223TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:387224 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347225 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]631f1322010-04-30 17:59:117226
7227 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:427228 proxy_config.set_auto_detect(true);
7229 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:117230
[email protected]631f1322010-04-30 17:59:117231 CapturingProxyResolver* capturing_proxy_resolver =
7232 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:387233 SessionDependencies session_deps(new ProxyService(
7234 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7235 NULL));
[email protected]631f1322010-04-30 17:59:117236
7237 HttpRequestInfo request;
7238 request.method = "GET";
7239 request.url = GURL("http://www.google.com/");
7240 request.load_flags = 0;
7241
7242 MockRead data_reads[] = {
7243 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357244 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:117245 MockRead("hello world"),
7246 MockRead(true, OK),
7247 };
7248
7249 StaticSocketDataProvider first_transaction(
7250 data_reads, arraysize(data_reads), NULL, 0);
7251 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7252
7253 SSLSocketDataProvider ssl(true, OK);
7254 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:207255 ssl.next_proto = "spdy/2.1";
[email protected]65041fa2010-05-21 06:56:537256 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:207257 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]631f1322010-04-30 17:59:117258 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7259
[email protected]2bd93022010-07-17 00:58:447260 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:117261 MockWrite spdy_writes[] = {
7262 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7263 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:427264 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:137265 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:117266 };
7267
[email protected]d911f1b2010-05-05 22:39:427268 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7269
[email protected]2bd93022010-07-17 00:58:447270 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7271 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:117272 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:427273 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:137274 CreateMockRead(*resp.get(), 4), // 2, 4
7275 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:427276 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:117277 };
7278
[email protected]a1595312012-01-22 03:25:047279 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]d911f1b2010-05-05 22:39:427280 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:117281 spdy_reads, arraysize(spdy_reads),
7282 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047283 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]631f1322010-04-30 17:59:117284
[email protected]2d6728692011-03-12 01:39:557285 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7286 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7287 NULL, 0, NULL, 0);
7288 hanging_non_alternate_protocol_socket.set_connect_data(
7289 never_finishing_connect);
7290 session_deps.socket_factory.AddSocketDataProvider(
7291 &hanging_non_alternate_protocol_socket);
7292
[email protected]49639fa2011-12-20 23:22:417293 TestCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:117294
7295 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7296 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7297
[email protected]49639fa2011-12-20 23:22:417298 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117299 EXPECT_EQ(ERR_IO_PENDING, rv);
7300 EXPECT_EQ(OK, callback.WaitForResult());
7301
7302 const HttpResponseInfo* response = trans->GetResponseInfo();
7303 ASSERT_TRUE(response != NULL);
7304 ASSERT_TRUE(response->headers != NULL);
7305 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537306 EXPECT_FALSE(response->was_fetched_via_spdy);
7307 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117308
7309 std::string response_data;
7310 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7311 EXPECT_EQ("hello world", response_data);
7312
7313 trans.reset(new HttpNetworkTransaction(session));
7314
[email protected]49639fa2011-12-20 23:22:417315 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]631f1322010-04-30 17:59:117316 EXPECT_EQ(ERR_IO_PENDING, rv);
7317 EXPECT_EQ(OK, callback.WaitForResult());
7318
7319 response = trans->GetResponseInfo();
7320 ASSERT_TRUE(response != NULL);
7321 ASSERT_TRUE(response->headers != NULL);
7322 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537323 EXPECT_TRUE(response->was_fetched_via_spdy);
7324 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117325
7326 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7327 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557328 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427329 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117330 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427331 EXPECT_EQ("https://www.google.com/",
7332 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117333
[email protected]5285d972011-10-18 18:56:347334 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387335 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117336}
[email protected]631f1322010-04-30 17:59:117337
[email protected]2ff8b312010-04-26 22:20:547338TEST_F(HttpNetworkTransactionTest,
7339 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387340 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347341 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:547342 SessionDependencies session_deps;
7343
7344 HttpRequestInfo request;
7345 request.method = "GET";
7346 request.url = GURL("http://www.google.com/");
7347 request.load_flags = 0;
7348
7349 MockRead data_reads[] = {
7350 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357351 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547352 MockRead("hello world"),
7353 MockRead(true, OK),
7354 };
7355
7356 StaticSocketDataProvider first_transaction(
7357 data_reads, arraysize(data_reads), NULL, 0);
7358 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7359
7360 SSLSocketDataProvider ssl(true, OK);
7361 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:207362 ssl.next_proto = "spdy/2.1";
[email protected]65041fa2010-05-21 06:56:537363 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:207364 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]2ff8b312010-04-26 22:20:547365 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537366 // Make sure we use ssl for spdy here.
7367 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547368
[email protected]2bd93022010-07-17 00:58:447369 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137370 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547371
[email protected]2bd93022010-07-17 00:58:447372 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7373 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547374 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137375 CreateMockRead(*resp),
7376 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547377 MockRead(true, 0, 0),
7378 };
7379
[email protected]a1595312012-01-22 03:25:047380 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]2ff8b312010-04-26 22:20:547381 new DelayedSocketData(
7382 1, // wait for one write to finish before reading.
7383 spdy_reads, arraysize(spdy_reads),
7384 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:047385 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]2ff8b312010-04-26 22:20:547386
[email protected]83039bb2011-12-09 18:43:557387 TestCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:547388
7389 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7390
7391 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7392
[email protected]49639fa2011-12-20 23:22:417393 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547394 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417395 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547396
7397 const HttpResponseInfo* response = trans->GetResponseInfo();
7398 ASSERT_TRUE(response != NULL);
7399 ASSERT_TRUE(response->headers != NULL);
7400 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7401
7402 std::string response_data;
7403 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7404 EXPECT_EQ("hello world", response_data);
7405
7406 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387407 HostPortPair host_port_pair("www.google.com", 443);
7408 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547409 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317410 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287411 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:297412 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]02b0c342010-09-25 21:09:387413
7414 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7415 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287416 connection->Init(host_port_pair.ToString(),
7417 transport_params,
7418 LOWEST,
[email protected]6ecf2b92011-12-15 01:14:527419 callback.callback(),
[email protected]a42dbd142011-11-17 16:42:027420 session->GetTransportSocketPool(),
[email protected]02b0c342010-09-25 21:09:387421 BoundNetLog()));
[email protected]6ecf2b92011-12-15 01:14:527422 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]02b0c342010-09-25 21:09:387423
7424 SSLConfig ssl_config;
7425 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347426 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177427 SSLClientSocketContext context;
7428 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347429 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7430 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177431 NULL /* ssl_host_info */, context));
[email protected]83039bb2011-12-09 18:43:557432 EXPECT_EQ(ERR_IO_PENDING,
7433 ssl_connection->socket()->Connect(callback.callback()));
[email protected]02b0c342010-09-25 21:09:387434 EXPECT_EQ(OK, callback.WaitForResult());
7435
[email protected]9e1bdd32011-02-03 21:48:347436 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387437 true, OK));
7438
[email protected]2ff8b312010-04-26 22:20:547439 trans.reset(new HttpNetworkTransaction(session));
7440
[email protected]49639fa2011-12-20 23:22:417441 rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547442 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:417443 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]2ff8b312010-04-26 22:20:547444
7445 response = trans->GetResponseInfo();
7446 ASSERT_TRUE(response != NULL);
7447 ASSERT_TRUE(response->headers != NULL);
7448 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537449 EXPECT_TRUE(response->was_fetched_via_spdy);
7450 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547451
7452 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7453 EXPECT_EQ("hello!", response_data);
7454
[email protected]5285d972011-10-18 18:56:347455 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387456 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427457}
7458
[email protected]044de0642010-06-17 10:42:157459// GenerateAuthToken is a mighty big test.
7460// It tests all permutation of GenerateAuthToken behavior:
7461// - Synchronous and Asynchronous completion.
7462// - OK or error on completion.
7463// - Direct connection, non-authenticating proxy, and authenticating proxy.
7464// - HTTP or HTTPS backend (to include proxy tunneling).
7465// - Non-authenticating and authenticating backend.
7466//
[email protected]fe3b7dc2012-02-03 19:52:097467// In all, there are 44 reasonable permuations (for example, if there are
[email protected]044de0642010-06-17 10:42:157468// problems generating an auth token for an authenticating proxy, we don't
7469// need to test all permutations of the backend server).
7470//
7471// The test proceeds by going over each of the configuration cases, and
7472// potentially running up to three rounds in each of the tests. The TestConfig
7473// specifies both the configuration for the test as well as the expectations
7474// for the results.
7475TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507476 static const char kServer[] = "http://www.example.com";
7477 static const char kSecureServer[] = "https://www.example.com";
7478 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157479 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7480
7481 enum AuthTiming {
7482 AUTH_NONE,
7483 AUTH_SYNC,
7484 AUTH_ASYNC,
7485 };
7486
7487 const MockWrite kGet(
7488 "GET / HTTP/1.1\r\n"
7489 "Host: www.example.com\r\n"
7490 "Connection: keep-alive\r\n\r\n");
7491 const MockWrite kGetProxy(
7492 "GET http://www.example.com/ HTTP/1.1\r\n"
7493 "Host: www.example.com\r\n"
7494 "Proxy-Connection: keep-alive\r\n\r\n");
7495 const MockWrite kGetAuth(
7496 "GET / HTTP/1.1\r\n"
7497 "Host: www.example.com\r\n"
7498 "Connection: keep-alive\r\n"
7499 "Authorization: auth_token\r\n\r\n");
7500 const MockWrite kGetProxyAuth(
7501 "GET http://www.example.com/ HTTP/1.1\r\n"
7502 "Host: www.example.com\r\n"
7503 "Proxy-Connection: keep-alive\r\n"
7504 "Proxy-Authorization: auth_token\r\n\r\n");
7505 const MockWrite kGetAuthThroughProxy(
7506 "GET http://www.example.com/ HTTP/1.1\r\n"
7507 "Host: www.example.com\r\n"
7508 "Proxy-Connection: keep-alive\r\n"
7509 "Authorization: auth_token\r\n\r\n");
7510 const MockWrite kGetAuthWithProxyAuth(
7511 "GET http://www.example.com/ HTTP/1.1\r\n"
7512 "Host: www.example.com\r\n"
7513 "Proxy-Connection: keep-alive\r\n"
7514 "Proxy-Authorization: auth_token\r\n"
7515 "Authorization: auth_token\r\n\r\n");
7516 const MockWrite kConnect(
7517 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7518 "Host: www.example.com\r\n"
7519 "Proxy-Connection: keep-alive\r\n\r\n");
7520 const MockWrite kConnectProxyAuth(
7521 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7522 "Host: www.example.com\r\n"
7523 "Proxy-Connection: keep-alive\r\n"
7524 "Proxy-Authorization: auth_token\r\n\r\n");
7525
7526 const MockRead kSuccess(
7527 "HTTP/1.1 200 OK\r\n"
7528 "Content-Type: text/html; charset=iso-8859-1\r\n"
7529 "Content-Length: 3\r\n\r\n"
7530 "Yes");
7531 const MockRead kFailure(
7532 "Should not be called.");
7533 const MockRead kServerChallenge(
7534 "HTTP/1.1 401 Unauthorized\r\n"
7535 "WWW-Authenticate: Mock realm=server\r\n"
7536 "Content-Type: text/html; charset=iso-8859-1\r\n"
7537 "Content-Length: 14\r\n\r\n"
7538 "Unauthorized\r\n");
7539 const MockRead kProxyChallenge(
7540 "HTTP/1.1 407 Unauthorized\r\n"
7541 "Proxy-Authenticate: Mock realm=proxy\r\n"
7542 "Proxy-Connection: close\r\n"
7543 "Content-Type: text/html; charset=iso-8859-1\r\n"
7544 "Content-Length: 14\r\n\r\n"
7545 "Unauthorized\r\n");
7546 const MockRead kProxyConnected(
7547 "HTTP/1.1 200 Connection Established\r\n\r\n");
7548
7549 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7550 // no constructors, but the C++ compiler on Windows warns about
7551 // unspecified data in compound literals. So, moved to using constructors,
7552 // and TestRound's created with the default constructor should not be used.
7553 struct TestRound {
7554 TestRound()
7555 : expected_rv(ERR_UNEXPECTED),
7556 extra_write(NULL),
7557 extra_read(NULL) {
7558 }
7559 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7560 int expected_rv_arg)
7561 : write(write_arg),
7562 read(read_arg),
7563 expected_rv(expected_rv_arg),
7564 extra_write(NULL),
7565 extra_read(NULL) {
7566 }
7567 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7568 int expected_rv_arg, const MockWrite* extra_write_arg,
7569 const MockWrite* extra_read_arg)
7570 : write(write_arg),
7571 read(read_arg),
7572 expected_rv(expected_rv_arg),
7573 extra_write(extra_write_arg),
7574 extra_read(extra_read_arg) {
7575 }
7576 MockWrite write;
7577 MockRead read;
7578 int expected_rv;
7579 const MockWrite* extra_write;
7580 const MockRead* extra_read;
7581 };
7582
7583 static const int kNoSSL = 500;
7584
7585 struct TestConfig {
7586 const char* proxy_url;
7587 AuthTiming proxy_auth_timing;
7588 int proxy_auth_rv;
7589 const char* server_url;
7590 AuthTiming server_auth_timing;
7591 int server_auth_rv;
7592 int num_auth_rounds;
7593 int first_ssl_round;
7594 TestRound rounds[3];
7595 } test_configs[] = {
7596 // Non-authenticating HTTP server with a direct connection.
7597 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7598 { TestRound(kGet, kSuccess, OK)}},
7599 // Authenticating HTTP server with a direct connection.
7600 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7601 { TestRound(kGet, kServerChallenge, OK),
7602 TestRound(kGetAuth, kSuccess, OK)}},
7603 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7604 { TestRound(kGet, kServerChallenge, OK),
7605 TestRound(kGetAuth, kFailure, kAuthErr)}},
7606 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7607 { TestRound(kGet, kServerChallenge, OK),
7608 TestRound(kGetAuth, kSuccess, OK)}},
7609 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7610 { TestRound(kGet, kServerChallenge, OK),
7611 TestRound(kGetAuth, kFailure, kAuthErr)}},
7612 // Non-authenticating HTTP server through a non-authenticating proxy.
7613 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7614 { TestRound(kGetProxy, kSuccess, OK)}},
7615 // Authenticating HTTP server through a non-authenticating proxy.
7616 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7617 { TestRound(kGetProxy, kServerChallenge, OK),
7618 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7619 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7620 { TestRound(kGetProxy, kServerChallenge, OK),
7621 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7622 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7623 { TestRound(kGetProxy, kServerChallenge, OK),
7624 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7625 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7626 { TestRound(kGetProxy, kServerChallenge, OK),
7627 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7628 // Non-authenticating HTTP server through an authenticating proxy.
7629 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7630 { TestRound(kGetProxy, kProxyChallenge, OK),
7631 TestRound(kGetProxyAuth, kSuccess, OK)}},
7632 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7633 { TestRound(kGetProxy, kProxyChallenge, OK),
7634 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7635 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7636 { TestRound(kGetProxy, kProxyChallenge, OK),
7637 TestRound(kGetProxyAuth, kSuccess, OK)}},
7638 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7639 { TestRound(kGetProxy, kProxyChallenge, OK),
7640 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7641 // Authenticating HTTP server through an authenticating proxy.
7642 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7643 { TestRound(kGetProxy, kProxyChallenge, OK),
7644 TestRound(kGetProxyAuth, kServerChallenge, OK),
7645 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7646 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7647 { TestRound(kGetProxy, kProxyChallenge, OK),
7648 TestRound(kGetProxyAuth, kServerChallenge, OK),
7649 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7650 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7651 { TestRound(kGetProxy, kProxyChallenge, OK),
7652 TestRound(kGetProxyAuth, kServerChallenge, OK),
7653 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7654 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7655 { TestRound(kGetProxy, kProxyChallenge, OK),
7656 TestRound(kGetProxyAuth, kServerChallenge, OK),
7657 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7658 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7659 { TestRound(kGetProxy, kProxyChallenge, OK),
7660 TestRound(kGetProxyAuth, kServerChallenge, OK),
7661 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7662 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7663 { TestRound(kGetProxy, kProxyChallenge, OK),
7664 TestRound(kGetProxyAuth, kServerChallenge, OK),
7665 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7666 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7667 { TestRound(kGetProxy, kProxyChallenge, OK),
7668 TestRound(kGetProxyAuth, kServerChallenge, OK),
7669 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7670 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7671 { TestRound(kGetProxy, kProxyChallenge, OK),
7672 TestRound(kGetProxyAuth, kServerChallenge, OK),
7673 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7674 // Non-authenticating HTTPS server with a direct connection.
7675 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7676 { TestRound(kGet, kSuccess, OK)}},
7677 // Authenticating HTTPS server with a direct connection.
7678 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7679 { TestRound(kGet, kServerChallenge, OK),
7680 TestRound(kGetAuth, kSuccess, OK)}},
7681 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7682 { TestRound(kGet, kServerChallenge, OK),
7683 TestRound(kGetAuth, kFailure, kAuthErr)}},
7684 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7685 { TestRound(kGet, kServerChallenge, OK),
7686 TestRound(kGetAuth, kSuccess, OK)}},
7687 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7688 { TestRound(kGet, kServerChallenge, OK),
7689 TestRound(kGetAuth, kFailure, kAuthErr)}},
7690 // Non-authenticating HTTPS server with a non-authenticating proxy.
7691 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7692 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7693 // Authenticating HTTPS server through a non-authenticating proxy.
7694 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7695 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7696 TestRound(kGetAuth, kSuccess, OK)}},
7697 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7698 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7699 TestRound(kGetAuth, kFailure, kAuthErr)}},
7700 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7701 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7702 TestRound(kGetAuth, kSuccess, OK)}},
7703 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7704 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7705 TestRound(kGetAuth, kFailure, kAuthErr)}},
7706 // Non-Authenticating HTTPS server through an authenticating proxy.
7707 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7708 { TestRound(kConnect, kProxyChallenge, OK),
7709 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7710 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7711 { TestRound(kConnect, kProxyChallenge, OK),
7712 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7713 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7714 { TestRound(kConnect, kProxyChallenge, OK),
7715 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7716 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7717 { TestRound(kConnect, kProxyChallenge, OK),
7718 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7719 // Authenticating HTTPS server through an authenticating proxy.
7720 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7721 { TestRound(kConnect, kProxyChallenge, OK),
7722 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7723 &kGet, &kServerChallenge),
7724 TestRound(kGetAuth, kSuccess, OK)}},
7725 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7726 { TestRound(kConnect, kProxyChallenge, OK),
7727 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7728 &kGet, &kServerChallenge),
7729 TestRound(kGetAuth, kFailure, kAuthErr)}},
7730 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7731 { TestRound(kConnect, kProxyChallenge, OK),
7732 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7733 &kGet, &kServerChallenge),
7734 TestRound(kGetAuth, kSuccess, OK)}},
7735 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7736 { TestRound(kConnect, kProxyChallenge, OK),
7737 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7738 &kGet, &kServerChallenge),
7739 TestRound(kGetAuth, kFailure, kAuthErr)}},
7740 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7741 { TestRound(kConnect, kProxyChallenge, OK),
7742 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7743 &kGet, &kServerChallenge),
7744 TestRound(kGetAuth, kSuccess, OK)}},
7745 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7746 { TestRound(kConnect, kProxyChallenge, OK),
7747 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7748 &kGet, &kServerChallenge),
7749 TestRound(kGetAuth, kFailure, kAuthErr)}},
7750 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7751 { TestRound(kConnect, kProxyChallenge, OK),
7752 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7753 &kGet, &kServerChallenge),
7754 TestRound(kGetAuth, kSuccess, OK)}},
7755 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7756 { TestRound(kConnect, kProxyChallenge, OK),
7757 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7758 &kGet, &kServerChallenge),
7759 TestRound(kGetAuth, kFailure, kAuthErr)}},
7760 };
7761
7762 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157763 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087764 HttpAuthHandlerMock::Factory* auth_factory(
7765 new HttpAuthHandlerMock::Factory());
7766 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157767 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267768
7769 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157770 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087771 for (int n = 0; n < 2; n++) {
7772 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7773 std::string auth_challenge = "Mock realm=proxy";
7774 GURL origin(test_config.proxy_url);
7775 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7776 auth_challenge.end());
7777 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7778 origin, BoundNetLog());
7779 auth_handler->SetGenerateExpectation(
7780 test_config.proxy_auth_timing == AUTH_ASYNC,
7781 test_config.proxy_auth_rv);
7782 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7783 }
[email protected]044de0642010-06-17 10:42:157784 }
7785 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007786 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157787 std::string auth_challenge = "Mock realm=server";
7788 GURL origin(test_config.server_url);
7789 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7790 auth_challenge.end());
7791 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7792 origin, BoundNetLog());
7793 auth_handler->SetGenerateExpectation(
7794 test_config.server_auth_timing == AUTH_ASYNC,
7795 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087796 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157797 }
7798 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127799 session_deps.proxy_service.reset(
7800 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157801 } else {
[email protected]6104ea5d2011-04-27 21:37:127802 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157803 }
7804
7805 HttpRequestInfo request;
7806 request.method = "GET";
7807 request.url = GURL(test_config.server_url);
7808 request.load_flags = 0;
7809
[email protected]0b0bf032010-09-21 18:08:507810 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7811 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157812
7813 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7814 const TestRound& read_write_round = test_config.rounds[round];
7815
7816 // Set up expected reads and writes.
7817 MockRead reads[2];
7818 reads[0] = read_write_round.read;
7819 size_t length_reads = 1;
7820 if (read_write_round.extra_read) {
7821 reads[1] = *read_write_round.extra_read;
7822 length_reads = 2;
7823 }
7824
7825 MockWrite writes[2];
7826 writes[0] = read_write_round.write;
7827 size_t length_writes = 1;
7828 if (read_write_round.extra_write) {
7829 writes[1] = *read_write_round.extra_write;
7830 length_writes = 2;
7831 }
7832 StaticSocketDataProvider data_provider(
7833 reads, length_reads, writes, length_writes);
7834 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7835
7836 // Add an SSL sequence if necessary.
7837 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7838 if (round >= test_config.first_ssl_round)
7839 session_deps.socket_factory.AddSSLSocketDataProvider(
7840 &ssl_socket_data_provider);
7841
7842 // Start or restart the transaction.
[email protected]49639fa2011-12-20 23:22:417843 TestCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:157844 int rv;
7845 if (round == 0) {
[email protected]49639fa2011-12-20 23:22:417846 rv = trans.Start(&request, callback.callback(), BoundNetLog());
[email protected]044de0642010-06-17 10:42:157847 } else {
[email protected]49639fa2011-12-20 23:22:417848 rv = trans.RestartWithAuth(
7849 AuthCredentials(kFoo, kBar), callback.callback());
[email protected]044de0642010-06-17 10:42:157850 }
7851 if (rv == ERR_IO_PENDING)
7852 rv = callback.WaitForResult();
7853
7854 // Compare results with expected data.
7855 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507856 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157857 if (read_write_round.expected_rv == OK) {
[email protected]fe2255a2011-09-20 19:37:507858 ASSERT_TRUE(response != NULL);
[email protected]044de0642010-06-17 10:42:157859 } else {
7860 EXPECT_TRUE(response == NULL);
7861 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7862 continue;
7863 }
7864 if (round + 1 < test_config.num_auth_rounds) {
7865 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7866 } else {
7867 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7868 }
7869 }
[email protected]e5ae96a2010-04-14 20:12:457870 }
7871}
7872
[email protected]c871bce92010-07-15 21:51:147873TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7874 // Do multi-round authentication and make sure it works correctly.
7875 SessionDependencies session_deps;
7876 HttpAuthHandlerMock::Factory* auth_factory(
7877 new HttpAuthHandlerMock::Factory());
7878 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127879 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147880 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7881 session_deps.host_resolver->set_synchronous_mode(true);
7882
7883 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7884 auth_handler->set_connection_based(true);
7885 std::string auth_challenge = "Mock realm=server";
7886 GURL origin("http://www.example.com");
7887 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7888 auth_challenge.end());
7889 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7890 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087891 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147892
[email protected]c871bce92010-07-15 21:51:147893 int rv = OK;
7894 const HttpResponseInfo* response = NULL;
7895 HttpRequestInfo request;
7896 request.method = "GET";
7897 request.url = origin;
7898 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277899
7900 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107901
7902 // Use a TCP Socket Pool with only one connection per group. This is used
7903 // to validate that the TCP socket is not released to the pool between
7904 // each round of multi-round authentication.
7905 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287906 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7907 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107908 50, // Max sockets for pool
7909 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287910 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107911 session_deps.host_resolver.get(),
7912 &session_deps.socket_factory,
7913 session_deps.net_log);
[email protected]a42dbd142011-11-17 16:42:027914 MockClientSocketPoolManager* mock_pool_manager =
7915 new MockClientSocketPoolManager;
7916 mock_pool_manager->SetTransportSocketPool(transport_pool);
7917 session_peer.SetClientSocketPoolManager(mock_pool_manager);
[email protected]7ef4cbbb2011-02-06 11:19:107918
[email protected]cb9bf6ca2011-01-28 13:15:277919 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417920 TestCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:147921
7922 const MockWrite kGet(
7923 "GET / HTTP/1.1\r\n"
7924 "Host: www.example.com\r\n"
7925 "Connection: keep-alive\r\n\r\n");
7926 const MockWrite kGetAuth(
7927 "GET / HTTP/1.1\r\n"
7928 "Host: www.example.com\r\n"
7929 "Connection: keep-alive\r\n"
7930 "Authorization: auth_token\r\n\r\n");
7931
7932 const MockRead kServerChallenge(
7933 "HTTP/1.1 401 Unauthorized\r\n"
7934 "WWW-Authenticate: Mock realm=server\r\n"
7935 "Content-Type: text/html; charset=iso-8859-1\r\n"
7936 "Content-Length: 14\r\n\r\n"
7937 "Unauthorized\r\n");
7938 const MockRead kSuccess(
7939 "HTTP/1.1 200 OK\r\n"
7940 "Content-Type: text/html; charset=iso-8859-1\r\n"
7941 "Content-Length: 3\r\n\r\n"
7942 "Yes");
7943
7944 MockWrite writes[] = {
7945 // First round
7946 kGet,
7947 // Second round
7948 kGetAuth,
7949 // Third round
7950 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307951 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107952 kGetAuth,
7953 // Competing request
7954 kGet,
[email protected]c871bce92010-07-15 21:51:147955 };
7956 MockRead reads[] = {
7957 // First round
7958 kServerChallenge,
7959 // Second round
7960 kServerChallenge,
7961 // Third round
[email protected]eca50e122010-09-11 14:03:307962 kServerChallenge,
7963 // Fourth round
[email protected]c871bce92010-07-15 21:51:147964 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107965 // Competing response
7966 kSuccess,
[email protected]c871bce92010-07-15 21:51:147967 };
7968 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7969 writes, arraysize(writes));
7970 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7971
[email protected]7ef4cbbb2011-02-06 11:19:107972 const char* const kSocketGroup = "www.example.com:80";
7973
7974 // First 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->Start(&request, callback.callback(), BoundNetLog());
[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_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287983 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147984
[email protected]7ef4cbbb2011-02-06 11:19:107985 // In between rounds, another request comes in for the same domain.
7986 // It should not be able to grab the TCP socket that trans has already
7987 // claimed.
7988 scoped_ptr<HttpTransaction> trans_compete(
7989 new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:417990 TestCompletionCallback callback_compete;
7991 rv = trans_compete->Start(
7992 &request, callback_compete.callback(), BoundNetLog());
[email protected]7ef4cbbb2011-02-06 11:19:107993 EXPECT_EQ(ERR_IO_PENDING, rv);
7994 // callback_compete.WaitForResult at this point would stall forever,
7995 // since the HttpNetworkTransaction does not release the request back to
7996 // the pool until after authentication completes.
7997
7998 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147999 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:418000 rv = trans->RestartWithAuth(AuthCredentials(kFoo, kBar), callback.callback());
[email protected]c871bce92010-07-15 21:51:148001 if (rv == ERR_IO_PENDING)
8002 rv = callback.WaitForResult();
8003 EXPECT_EQ(OK, rv);
8004 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508005 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:148006 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:288007 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:148008
[email protected]7ef4cbbb2011-02-06 11:19:108009 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:148010 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:418011 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]c871bce92010-07-15 21:51:148012 if (rv == ERR_IO_PENDING)
8013 rv = callback.WaitForResult();
8014 EXPECT_EQ(OK, rv);
8015 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508016 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:148017 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:288018 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:308019
[email protected]7ef4cbbb2011-02-06 11:19:108020 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:308021 auth_handler->SetGenerateExpectation(false, OK);
[email protected]49639fa2011-12-20 23:22:418022 rv = trans->RestartWithAuth(AuthCredentials(), callback.callback());
[email protected]eca50e122010-09-11 14:03:308023 if (rv == ERR_IO_PENDING)
8024 rv = callback.WaitForResult();
8025 EXPECT_EQ(OK, rv);
8026 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508027 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:308028 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:288029 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:108030
8031 // Read the body since the fourth round was successful. This will also
8032 // release the socket back to the pool.
8033 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
[email protected]49639fa2011-12-20 23:22:418034 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108035 if (rv == ERR_IO_PENDING)
8036 rv = callback.WaitForResult();
8037 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:418038 rv = trans->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108039 EXPECT_EQ(0, rv);
8040 // There are still 0 idle sockets, since the trans_compete transaction
8041 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:288042 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:108043
8044 // The competing request can now finish. Wait for the headers and then
8045 // read the body.
8046 rv = callback_compete.WaitForResult();
8047 EXPECT_EQ(OK, rv);
[email protected]49639fa2011-12-20 23:22:418048 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108049 if (rv == ERR_IO_PENDING)
8050 rv = callback.WaitForResult();
8051 EXPECT_EQ(3, rv);
[email protected]49639fa2011-12-20 23:22:418052 rv = trans_compete->Read(io_buf, io_buf->size(), callback.callback());
[email protected]7ef4cbbb2011-02-06 11:19:108053 EXPECT_EQ(0, rv);
8054
8055 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:288056 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:148057}
8058
[email protected]aeaca1f2010-04-20 22:05:218059class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
8060 public:
[email protected]06650c52010-06-03 00:49:178061 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:218062 : fail_all_(fail_all) {
8063 }
8064
8065 virtual MockRead GetNextRead() {
8066 if (fail_all_)
8067 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
8068
8069 return MockRead(false /* async */,
8070 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
8071 }
8072
8073 virtual MockWriteResult OnWrite(const std::string& data) {
8074 return MockWriteResult(false /* async */, data.size());
8075 }
8076
8077 void Reset() {
8078 }
8079
8080 private:
8081 const bool fail_all_;
8082};
8083
8084// Test that we restart a connection when we see a decompression failure from
8085// the peer during the handshake. (In the real world we'll restart with SSLv3
8086// and we won't offer DEFLATE in that case.)
8087TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
8088 HttpRequestInfo request;
8089 request.method = "GET";
8090 request.url = GURL("https://tlsdecompressionfailure.example.com/");
8091 request.load_flags = 0;
8092
8093 SessionDependencies session_deps;
8094 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8095 false /* fail all reads */);
8096 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8097 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:118098 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:218099 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
8100 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8101 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8102 session_deps.socket_factory.AddSSLSocketDataProvider(
8103 &ssl_socket_data_provider1);
8104 session_deps.socket_factory.AddSSLSocketDataProvider(
8105 &ssl_socket_data_provider2);
8106
[email protected]e60e47a2010-07-14 03:37:188107 // Work around http://crbug.com/37454
8108 StaticSocketDataProvider bug37454_connection;
8109 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
8110 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
8111
[email protected]aeaca1f2010-04-20 22:05:218112 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8113 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418114 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218115
[email protected]49639fa2011-12-20 23:22:418116 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218117 EXPECT_EQ(ERR_IO_PENDING, rv);
8118 EXPECT_EQ(OK, callback.WaitForResult());
8119
8120 const HttpResponseInfo* response = trans->GetResponseInfo();
8121 ASSERT_TRUE(response != NULL);
8122 ASSERT_TRUE(response->headers != NULL);
8123 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8124
8125 std::string response_data;
8126 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8127 EXPECT_EQ("ok.", response_data);
8128}
8129
8130// Test that we restart a connection if we get a decompression failure from the
8131// peer while reading the first bytes from the connection. This occurs when the
8132// peer cannot handle DEFLATE but we're using False Start, so we don't notice
8133// in the handshake.
8134TEST_F(HttpNetworkTransactionTest,
8135 RestartAfterTLSDecompressionFailureWithFalseStart) {
8136 HttpRequestInfo request;
8137 request.method = "GET";
8138 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
8139 request.load_flags = 0;
8140
8141 SessionDependencies session_deps;
8142 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8143 true /* fail all reads */);
8144 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8145 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
8146 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
8147 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8148 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8149 session_deps.socket_factory.AddSSLSocketDataProvider(
8150 &ssl_socket_data_provider1);
8151 session_deps.socket_factory.AddSSLSocketDataProvider(
8152 &ssl_socket_data_provider2);
8153
8154 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8155 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418156 TestCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218157
[email protected]49639fa2011-12-20 23:22:418158 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218159 EXPECT_EQ(ERR_IO_PENDING, rv);
8160 EXPECT_EQ(OK, callback.WaitForResult());
8161
8162 const HttpResponseInfo* response = trans->GetResponseInfo();
8163 ASSERT_TRUE(response != NULL);
8164 ASSERT_TRUE(response->headers != NULL);
8165 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8166
8167 std::string response_data;
8168 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8169 EXPECT_EQ("ok.", response_data);
8170}
8171
[email protected]65041fa2010-05-21 06:56:538172// This tests the case that a request is issued via http instead of spdy after
8173// npn is negotiated.
8174TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:388175 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348176 HttpStreamFactory::set_next_protos(
8177 MakeNextProtos("http/1.1", "http1.1", NULL));
[email protected]65041fa2010-05-21 06:56:538178 SessionDependencies session_deps;
8179 HttpRequestInfo request;
8180 request.method = "GET";
8181 request.url = GURL("https://www.google.com/");
8182 request.load_flags = 0;
8183
8184 MockWrite data_writes[] = {
8185 MockWrite("GET / HTTP/1.1\r\n"
8186 "Host: www.google.com\r\n"
8187 "Connection: keep-alive\r\n\r\n"),
8188 };
8189
8190 MockRead data_reads[] = {
8191 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:358192 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:538193 MockRead("hello world"),
8194 MockRead(false, OK),
8195 };
8196
8197 SSLSocketDataProvider ssl(true, OK);
8198 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8199 ssl.next_proto = "http/1.1";
[email protected]c30bcce2011-12-20 17:50:518200 ssl.protocol_negotiated = SSLClientSocket::kProtoHTTP11;
[email protected]65041fa2010-05-21 06:56:538201
8202 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8203
8204 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8205 data_writes, arraysize(data_writes));
8206 session_deps.socket_factory.AddSocketDataProvider(&data);
8207
[email protected]49639fa2011-12-20 23:22:418208 TestCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:538209
8210 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8211 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8212
[email protected]49639fa2011-12-20 23:22:418213 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]65041fa2010-05-21 06:56:538214
8215 EXPECT_EQ(ERR_IO_PENDING, rv);
8216 EXPECT_EQ(OK, callback.WaitForResult());
8217
8218 const HttpResponseInfo* response = trans->GetResponseInfo();
8219 ASSERT_TRUE(response != NULL);
8220 ASSERT_TRUE(response->headers != NULL);
8221 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8222
8223 std::string response_data;
8224 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8225 EXPECT_EQ("hello world", response_data);
8226
8227 EXPECT_FALSE(response->was_fetched_via_spdy);
8228 EXPECT_TRUE(response->was_npn_negotiated);
8229
[email protected]5285d972011-10-18 18:56:348230 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388231 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:538232}
[email protected]26ef6582010-06-24 02:30:478233
8234TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8235 // Simulate the SSL handshake completing with an NPN negotiation
8236 // followed by an immediate server closing of the socket.
8237 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:388238 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348239 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]26ef6582010-06-24 02:30:478240 SessionDependencies session_deps;
8241
8242 HttpRequestInfo request;
8243 request.method = "GET";
8244 request.url = GURL("https://www.google.com/");
8245 request.load_flags = 0;
8246
8247 SSLSocketDataProvider ssl(true, OK);
8248 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208249 ssl.next_proto = "spdy/2.1";
[email protected]26ef6582010-06-24 02:30:478250 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208251 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]26ef6582010-06-24 02:30:478252 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8253
[email protected]2bd93022010-07-17 00:58:448254 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:138255 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:478256
8257 MockRead spdy_reads[] = {
8258 MockRead(false, 0, 0) // Not async - return 0 immediately.
8259 };
8260
[email protected]a1595312012-01-22 03:25:048261 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]26ef6582010-06-24 02:30:478262 new DelayedSocketData(
8263 0, // don't wait in this case, immediate hangup.
8264 spdy_reads, arraysize(spdy_reads),
8265 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048266 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]26ef6582010-06-24 02:30:478267
[email protected]49639fa2011-12-20 23:22:418268 TestCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:478269
8270 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8271 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8272
[email protected]49639fa2011-12-20 23:22:418273 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]26ef6582010-06-24 02:30:478274 EXPECT_EQ(ERR_IO_PENDING, rv);
8275 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8276
[email protected]5285d972011-10-18 18:56:348277 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388278 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:478279}
[email protected]65d34382010-07-01 18:12:268280
[email protected]f45c1ee2010-08-03 00:54:308281TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8282 // This test ensures that the URL passed into the proxy is upgraded
8283 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:388284 HttpStreamFactory::set_use_alternate_protocols(true);
8285 HttpStreamFactory::set_next_protos(
[email protected]42baef7a2011-12-10 04:52:108286 MakeNextProtos(
8287 "http/1.1", "http1.1", "spdy/2.1", "spdy/2", "spdy", NULL));
[email protected]f45c1ee2010-08-03 00:54:308288
[email protected]81cdfcd2010-10-16 00:49:008289 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:308290 HttpAuthHandlerMock::Factory* auth_factory =
8291 new HttpAuthHandlerMock::Factory();
[email protected]767257802011-12-14 17:33:188292 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
8293 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:308294 auth_factory->set_do_init_from_challenge(true);
8295 session_deps.http_auth_handler_factory.reset(auth_factory);
8296
8297 HttpRequestInfo request;
8298 request.method = "GET";
8299 request.url = GURL("http://www.google.com");
8300 request.load_flags = 0;
8301
8302 // First round goes unauthenticated through the proxy.
8303 MockWrite data_writes_1[] = {
8304 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8305 "Host: www.google.com\r\n"
8306 "Proxy-Connection: keep-alive\r\n"
8307 "\r\n"),
8308 };
8309 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:598310 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:308311 MockRead("HTTP/1.1 200 OK\r\n"
[email protected]1ad77dc2012-01-27 03:51:208312 "Alternate-Protocol: 443:npn-spdy/2.1\r\n"
[email protected]f45c1ee2010-08-03 00:54:308313 "Proxy-Connection: close\r\n"
8314 "\r\n"),
8315 };
8316 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8317 data_writes_1, arraysize(data_writes_1));
8318
8319 // Second round tries to tunnel to www.google.com due to the
8320 // Alternate-Protocol announcement in the first round. It fails due
8321 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:598322 // After the failure, a tunnel is established to www.google.com using
8323 // Proxy-Authorization headers. There is then a SPDY request round.
8324 //
[email protected]fe3b7dc2012-02-03 19:52:098325 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8326 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8327 // does a Disconnect and Connect on the same socket, rather than trying
8328 // to obtain a new one.
8329 //
[email protected]394816e92010-08-03 07:38:598330 // NOTE: Originally, the proxy response to the second CONNECT request
8331 // simply returned another 407 so the unit test could skip the SSL connection
8332 // establishment and SPDY framing issues. Alas, the
8333 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308334 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598335
[email protected]f45c1ee2010-08-03 00:54:308336 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8337 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8338 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8339
[email protected]394816e92010-08-03 07:38:598340 MockWrite data_writes_2[] = {
8341 // First connection attempt without Proxy-Authorization.
8342 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8343 "Host: www.google.com\r\n"
8344 "Proxy-Connection: keep-alive\r\n"
8345 "\r\n"),
8346
8347 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308348 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8349 "Host: www.google.com\r\n"
8350 "Proxy-Connection: keep-alive\r\n"
8351 "Proxy-Authorization: auth_token\r\n"
8352 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308353
[email protected]394816e92010-08-03 07:38:598354 // SPDY request
8355 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308356 };
[email protected]394816e92010-08-03 07:38:598357 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8358 "Proxy-Authenticate: Mock\r\n"
8359 "Proxy-Connection: close\r\n"
8360 "\r\n");
8361 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8362 MockRead data_reads_2[] = {
8363 // First connection attempt fails
8364 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8365 MockRead(true, kRejectConnectResponse,
8366 arraysize(kRejectConnectResponse) - 1, 1),
8367
8368 // Second connection attempt passes
8369 MockRead(true, kAcceptConnectResponse,
[email protected]fe3b7dc2012-02-03 19:52:098370 arraysize(kAcceptConnectResponse) -1, 4),
[email protected]394816e92010-08-03 07:38:598371
8372 // SPDY response
[email protected]fe3b7dc2012-02-03 19:52:098373 CreateMockRead(*resp.get(), 6),
8374 CreateMockRead(*data.get(), 6),
8375 MockRead(true, 0, 0, 6),
[email protected]394816e92010-08-03 07:38:598376 };
[email protected]a1595312012-01-22 03:25:048377 scoped_ptr<OrderedSocketData> data_2(
[email protected]394816e92010-08-03 07:38:598378 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8379 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308380
8381 SSLSocketDataProvider ssl(true, OK);
8382 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208383 ssl.next_proto = "spdy/2.1";
[email protected]f45c1ee2010-08-03 00:54:308384 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208385 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]f45c1ee2010-08-03 00:54:308386
[email protected]2d6728692011-03-12 01:39:558387 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8388 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8389 NULL, 0, NULL, 0);
8390 hanging_non_alternate_protocol_socket.set_connect_data(
8391 never_finishing_connect);
8392
[email protected]f45c1ee2010-08-03 00:54:308393 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598394 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308395 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558396 session_deps.socket_factory.AddSocketDataProvider(
8397 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308398 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8399
8400 // First round should work and provide the Alternate-Protocol state.
[email protected]49639fa2011-12-20 23:22:418401 TestCompletionCallback callback_1;
[email protected]f45c1ee2010-08-03 00:54:308402 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418403 int rv = trans_1->Start(&request, callback_1.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308404 EXPECT_EQ(ERR_IO_PENDING, rv);
8405 EXPECT_EQ(OK, callback_1.WaitForResult());
8406
8407 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]49639fa2011-12-20 23:22:418408 TestCompletionCallback callback_2;
[email protected]f45c1ee2010-08-03 00:54:308409 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
[email protected]49639fa2011-12-20 23:22:418410 rv = trans_2->Start(&request, callback_2.callback(), BoundNetLog());
[email protected]f45c1ee2010-08-03 00:54:308411 EXPECT_EQ(ERR_IO_PENDING, rv);
8412 EXPECT_EQ(OK, callback_2.WaitForResult());
8413 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508414 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:308415 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8416
8417 // Restart with auth. Tunnel should work and response received.
[email protected]49639fa2011-12-20 23:22:418418 TestCompletionCallback callback_3;
8419 rv = trans_2->RestartWithAuth(
8420 AuthCredentials(kFoo, kBar), callback_3.callback());
[email protected]f45c1ee2010-08-03 00:54:308421 EXPECT_EQ(ERR_IO_PENDING, rv);
8422 EXPECT_EQ(OK, callback_3.WaitForResult());
8423
8424 // After all that work, these two lines (or actually, just the scheme) are
8425 // what this test is all about. Make sure it happens correctly.
[email protected]767257802011-12-14 17:33:188426 const GURL& request_url = auth_handler->request_url();
[email protected]f45c1ee2010-08-03 00:54:308427 EXPECT_EQ("https", request_url.scheme());
8428 EXPECT_EQ("www.google.com", request_url.host());
8429
[email protected]5285d972011-10-18 18:56:348430 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388431 HttpStreamFactory::set_use_alternate_protocols(false);
8432}
8433
8434// Test that if we cancel the transaction as the connection is completing, that
8435// everything tears down correctly.
8436TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8437 // Setup everything about the connection to complete synchronously, so that
8438 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8439 // for is the callback from the HttpStreamRequest.
8440 // Then cancel the transaction.
8441 // Verify that we don't crash.
8442 MockConnect mock_connect(false, OK);
8443 MockRead data_reads[] = {
8444 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8445 MockRead(false, "hello world"),
8446 MockRead(false, OK),
8447 };
8448
[email protected]8e6441ca2010-08-19 05:56:388449 HttpRequestInfo request;
8450 request.method = "GET";
8451 request.url = GURL("http://www.google.com/");
8452 request.load_flags = 0;
8453
[email protected]cb9bf6ca2011-01-28 13:15:278454 SessionDependencies session_deps;
8455 session_deps.host_resolver->set_synchronous_mode(true);
8456 scoped_ptr<HttpTransaction> trans(
8457 new HttpNetworkTransaction(CreateSession(&session_deps)));
8458
[email protected]8e6441ca2010-08-19 05:56:388459 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8460 data.set_connect_data(mock_connect);
8461 session_deps.socket_factory.AddSocketDataProvider(&data);
8462
[email protected]49639fa2011-12-20 23:22:418463 TestCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:388464
8465 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]49639fa2011-12-20 23:22:418466 int rv = trans->Start(&request, callback.callback(), log.bound());
[email protected]8e6441ca2010-08-19 05:56:388467 EXPECT_EQ(ERR_IO_PENDING, rv);
8468 trans.reset(); // Cancel the transaction here.
8469
8470 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308471}
8472
[email protected]76a505b2010-08-25 06:23:008473// Test a basic GET request through a proxy.
8474TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008475 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008476 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8477 session_deps.net_log = log.bound().net_log();
8478 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8479
[email protected]76a505b2010-08-25 06:23:008480 HttpRequestInfo request;
8481 request.method = "GET";
8482 request.url = GURL("http://www.google.com/");
8483
8484 MockWrite data_writes1[] = {
8485 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8486 "Host: www.google.com\r\n"
8487 "Proxy-Connection: keep-alive\r\n\r\n"),
8488 };
8489
8490 MockRead data_reads1[] = {
8491 MockRead("HTTP/1.1 200 OK\r\n"),
8492 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8493 MockRead("Content-Length: 100\r\n\r\n"),
8494 MockRead(false, OK),
8495 };
8496
8497 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8498 data_writes1, arraysize(data_writes1));
8499 session_deps.socket_factory.AddSocketDataProvider(&data1);
8500
[email protected]49639fa2011-12-20 23:22:418501 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008502
[email protected]0b0bf032010-09-21 18:08:508503 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8504
[email protected]49639fa2011-12-20 23:22:418505 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008506 EXPECT_EQ(ERR_IO_PENDING, rv);
8507
8508 rv = callback1.WaitForResult();
8509 EXPECT_EQ(OK, rv);
8510
8511 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508512 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008513
8514 EXPECT_TRUE(response->headers->IsKeepAlive());
8515 EXPECT_EQ(200, response->headers->response_code());
8516 EXPECT_EQ(100, response->headers->GetContentLength());
8517 EXPECT_TRUE(response->was_fetched_via_proxy);
8518 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8519}
8520
8521// Test a basic HTTPS GET request through a proxy.
8522TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008523 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008524 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8525 session_deps.net_log = log.bound().net_log();
8526 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8527
[email protected]76a505b2010-08-25 06:23:008528 HttpRequestInfo request;
8529 request.method = "GET";
8530 request.url = GURL("https://www.google.com/");
8531
8532 // Since we have proxy, should try to establish tunnel.
8533 MockWrite data_writes1[] = {
8534 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8535 "Host: www.google.com\r\n"
8536 "Proxy-Connection: keep-alive\r\n\r\n"),
8537
8538 MockWrite("GET / HTTP/1.1\r\n"
8539 "Host: www.google.com\r\n"
8540 "Connection: keep-alive\r\n\r\n"),
8541 };
8542
8543 MockRead data_reads1[] = {
8544 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8545
8546 MockRead("HTTP/1.1 200 OK\r\n"),
8547 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8548 MockRead("Content-Length: 100\r\n\r\n"),
8549 MockRead(false, OK),
8550 };
8551
8552 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8553 data_writes1, arraysize(data_writes1));
8554 session_deps.socket_factory.AddSocketDataProvider(&data1);
8555 SSLSocketDataProvider ssl(true, OK);
8556 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8557
[email protected]49639fa2011-12-20 23:22:418558 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008559
[email protected]0b0bf032010-09-21 18:08:508560 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8561
[email protected]49639fa2011-12-20 23:22:418562 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008563 EXPECT_EQ(ERR_IO_PENDING, rv);
8564
8565 rv = callback1.WaitForResult();
8566 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408567 net::CapturingNetLog::EntryList entries;
8568 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008569 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408570 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008571 NetLog::PHASE_NONE);
8572 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408573 entries, pos,
[email protected]76a505b2010-08-25 06:23:008574 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8575 NetLog::PHASE_NONE);
8576
8577 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508578 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008579
8580 EXPECT_TRUE(response->headers->IsKeepAlive());
8581 EXPECT_EQ(200, response->headers->response_code());
8582 EXPECT_EQ(100, response->headers->GetContentLength());
8583 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8584 EXPECT_TRUE(response->was_fetched_via_proxy);
8585}
8586
8587// Test a basic HTTPS GET request through a proxy, but the server hangs up
8588// while establishing the tunnel.
8589TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008590 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008591 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8592 session_deps.net_log = log.bound().net_log();
8593 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8594
[email protected]76a505b2010-08-25 06:23:008595 HttpRequestInfo request;
8596 request.method = "GET";
8597 request.url = GURL("https://www.google.com/");
8598
8599 // Since we have proxy, should try to establish tunnel.
8600 MockWrite data_writes1[] = {
8601 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8602 "Host: www.google.com\r\n"
8603 "Proxy-Connection: keep-alive\r\n\r\n"),
8604
8605 MockWrite("GET / HTTP/1.1\r\n"
8606 "Host: www.google.com\r\n"
8607 "Connection: keep-alive\r\n\r\n"),
8608 };
8609
8610 MockRead data_reads1[] = {
8611 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8612 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8613 MockRead(true, 0, 0), // EOF
8614 };
8615
8616 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8617 data_writes1, arraysize(data_writes1));
8618 session_deps.socket_factory.AddSocketDataProvider(&data1);
8619 SSLSocketDataProvider ssl(true, OK);
8620 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8621
[email protected]49639fa2011-12-20 23:22:418622 TestCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008623
[email protected]0b0bf032010-09-21 18:08:508624 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8625
[email protected]49639fa2011-12-20 23:22:418626 int rv = trans->Start(&request, callback1.callback(), log.bound());
[email protected]76a505b2010-08-25 06:23:008627 EXPECT_EQ(ERR_IO_PENDING, rv);
8628
8629 rv = callback1.WaitForResult();
8630 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408631 net::CapturingNetLog::EntryList entries;
8632 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008633 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408634 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008635 NetLog::PHASE_NONE);
8636 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408637 entries, pos,
[email protected]76a505b2010-08-25 06:23:008638 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8639 NetLog::PHASE_NONE);
8640}
8641
[email protected]749eefa82010-09-13 22:14:038642// Test for crbug.com/55424.
8643TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8644 SessionDependencies session_deps;
8645
8646 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8647 "https://www.google.com", false, 1, LOWEST));
8648 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8649
8650 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8651 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8652 MockRead spdy_reads[] = {
8653 CreateMockRead(*resp),
8654 CreateMockRead(*data),
8655 MockRead(true, 0, 0),
8656 };
8657
[email protected]a1595312012-01-22 03:25:048658 scoped_ptr<DelayedSocketData> spdy_data(
[email protected]749eefa82010-09-13 22:14:038659 new DelayedSocketData(
8660 1, // wait for one write to finish before reading.
8661 spdy_reads, arraysize(spdy_reads),
8662 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:048663 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]749eefa82010-09-13 22:14:038664
8665 SSLSocketDataProvider ssl(true, OK);
8666 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:208667 ssl.next_proto = "spdy/2.1";
[email protected]749eefa82010-09-13 22:14:038668 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:208669 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]749eefa82010-09-13 22:14:038670 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8671
8672 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8673
8674 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388675 HostPortPair host_port_pair("www.google.com", 443);
8676 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038677 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318678 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288679 scoped_refptr<TransportSocketParams> transport_params(
[email protected]acdda412011-11-15 21:21:298680 new TransportSocketParams(host_port_pair, MEDIUM, false, false));
[email protected]6ecf2b92011-12-15 01:14:528681 TestCompletionCallback callback;
[email protected]02b0c342010-09-25 21:09:388682
8683 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8684 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288685 connection->Init(host_port_pair.ToString(), transport_params,
[email protected]6ecf2b92011-12-15 01:14:528686 LOWEST, callback.callback(),
[email protected]a42dbd142011-11-17 16:42:028687 session->GetTransportSocketPool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388688 EXPECT_EQ(OK, callback.WaitForResult());
8689 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038690
8691 HttpRequestInfo request;
8692 request.method = "GET";
8693 request.url = GURL("https://www.google.com/");
8694 request.load_flags = 0;
8695
8696 // This is the important line that marks this as a preconnect.
8697 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8698
8699 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8700
[email protected]49639fa2011-12-20 23:22:418701 int rv = trans->Start(&request, callback.callback(), BoundNetLog());
[email protected]749eefa82010-09-13 22:14:038702 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:418703 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]749eefa82010-09-13 22:14:038704}
8705
[email protected]73b8dd222010-11-11 19:55:248706// Given a net error, cause that error to be returned from the first Write()
8707// call and verify that the HttpTransaction fails with that error.
8708static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278709 net::HttpRequestInfo request_info;
8710 request_info.url = GURL("https://www.example.com/");
8711 request_info.method = "GET";
8712 request_info.load_flags = net::LOAD_NORMAL;
8713
[email protected]73b8dd222010-11-11 19:55:248714 SessionDependencies session_deps;
8715
8716 SSLSocketDataProvider ssl_data(async, OK);
8717 net::MockWrite data_writes[] = {
8718 net::MockWrite(async, error),
8719 };
8720 net::StaticSocketDataProvider data(NULL, 0,
8721 data_writes, arraysize(data_writes));
8722 session_deps.socket_factory.AddSocketDataProvider(&data);
8723 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8724
8725 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8726 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8727
[email protected]49639fa2011-12-20 23:22:418728 TestCompletionCallback callback;
8729 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]73b8dd222010-11-11 19:55:248730 if (rv == net::ERR_IO_PENDING)
8731 rv = callback.WaitForResult();
8732 ASSERT_EQ(error, rv);
8733}
8734
8735TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8736 // Just check a grab bag of cert errors.
8737 static const int kErrors[] = {
8738 ERR_CERT_COMMON_NAME_INVALID,
8739 ERR_CERT_AUTHORITY_INVALID,
8740 ERR_CERT_DATE_INVALID,
8741 };
8742 for (size_t i = 0; i < arraysize(kErrors); i++) {
8743 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8744 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8745 }
8746}
8747
[email protected]bd0b6772011-01-11 19:59:308748// Ensure that a client certificate is removed from the SSL client auth
8749// cache when:
8750// 1) No proxy is involved.
8751// 2) TLS False Start is disabled.
8752// 3) The initial TLS handshake requests a client certificate.
8753// 4) The client supplies an invalid/unacceptable certificate.
8754TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278755 net::HttpRequestInfo request_info;
8756 request_info.url = GURL("https://www.example.com/");
8757 request_info.method = "GET";
8758 request_info.load_flags = net::LOAD_NORMAL;
8759
[email protected]bd0b6772011-01-11 19:59:308760 SessionDependencies session_deps;
8761
8762 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8763 cert_request->host_and_port = "www.example.com:443";
8764
8765 // [ssl_]data1 contains the data for the first SSL handshake. When a
8766 // CertificateRequest is received for the first time, the handshake will
8767 // be aborted to allow the caller to provide a certificate.
8768 SSLSocketDataProvider ssl_data1(true /* async */,
8769 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8770 ssl_data1.cert_request_info = cert_request.get();
8771 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8772 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8773 session_deps.socket_factory.AddSocketDataProvider(&data1);
8774
8775 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8776 // False Start is not being used, the result of the SSL handshake will be
8777 // returned as part of the SSLClientSocket::Connect() call. This test
8778 // matches the result of a server sending a handshake_failure alert,
8779 // rather than a Finished message, because it requires a client
8780 // certificate and none was supplied.
8781 SSLSocketDataProvider ssl_data2(true /* async */,
8782 net::ERR_SSL_PROTOCOL_ERROR);
8783 ssl_data2.cert_request_info = cert_request.get();
8784 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8785 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8786 session_deps.socket_factory.AddSocketDataProvider(&data2);
8787
8788 // [ssl_]data3 contains the data for the third SSL handshake. When a
8789 // connection to a server fails during an SSL handshake,
8790 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8791 // connection was attempted with TLSv1. This is transparent to the caller
8792 // of the HttpNetworkTransaction. Because this test failure is due to
8793 // requiring a client certificate, this fallback handshake should also
8794 // fail.
8795 SSLSocketDataProvider ssl_data3(true /* async */,
8796 net::ERR_SSL_PROTOCOL_ERROR);
8797 ssl_data3.cert_request_info = cert_request.get();
8798 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8799 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8800 session_deps.socket_factory.AddSocketDataProvider(&data3);
8801
8802 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8803 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8804
[email protected]bd0b6772011-01-11 19:59:308805 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]49639fa2011-12-20 23:22:418806 TestCompletionCallback callback;
8807 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308808 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8809
8810 // Complete the SSL handshake, which should abort due to requiring a
8811 // client certificate.
8812 rv = callback.WaitForResult();
8813 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8814
8815 // Indicate that no certificate should be supplied. From the perspective
8816 // of SSLClientCertCache, NULL is just as meaningful as a real
8817 // certificate, so this is the same as supply a
8818 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418819 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308820 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8821
8822 // Ensure the certificate was added to the client auth cache before
8823 // allowing the connection to continue restarting.
8824 scoped_refptr<X509Certificate> client_cert;
8825 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8826 &client_cert));
8827 ASSERT_EQ(NULL, client_cert.get());
8828
8829 // Restart the handshake. This will consume ssl_data2, which fails, and
8830 // then consume ssl_data3, which should also fail. The result code is
8831 // checked against what ssl_data3 should return.
8832 rv = callback.WaitForResult();
8833 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8834
8835 // Ensure that the client certificate is removed from the cache on a
8836 // handshake failure.
8837 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8838 &client_cert));
8839}
8840
8841// Ensure that a client certificate is removed from the SSL client auth
8842// cache when:
8843// 1) No proxy is involved.
8844// 2) TLS False Start is enabled.
8845// 3) The initial TLS handshake requests a client certificate.
8846// 4) The client supplies an invalid/unacceptable certificate.
8847TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278848 net::HttpRequestInfo request_info;
8849 request_info.url = GURL("https://www.example.com/");
8850 request_info.method = "GET";
8851 request_info.load_flags = net::LOAD_NORMAL;
8852
[email protected]bd0b6772011-01-11 19:59:308853 SessionDependencies session_deps;
8854
8855 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8856 cert_request->host_and_port = "www.example.com:443";
8857
8858 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8859 // return successfully after reading up to the peer's Certificate message.
8860 // This is to allow the caller to call SSLClientSocket::Write(), which can
8861 // enqueue application data to be sent in the same packet as the
8862 // ChangeCipherSpec and Finished messages.
8863 // The actual handshake will be finished when SSLClientSocket::Read() is
8864 // called, which expects to process the peer's ChangeCipherSpec and
8865 // Finished messages. If there was an error negotiating with the peer,
8866 // such as due to the peer requiring a client certificate when none was
8867 // supplied, the alert sent by the peer won't be processed until Read() is
8868 // called.
8869
8870 // Like the non-False Start case, when a client certificate is requested by
8871 // the peer, the handshake is aborted during the Connect() call.
8872 // [ssl_]data1 represents the initial SSL handshake with the peer.
8873 SSLSocketDataProvider ssl_data1(true /* async */,
8874 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8875 ssl_data1.cert_request_info = cert_request.get();
8876 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8877 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8878 session_deps.socket_factory.AddSocketDataProvider(&data1);
8879
8880 // When a client certificate is supplied, Connect() will not be aborted
8881 // when the peer requests the certificate. Instead, the handshake will
8882 // artificially succeed, allowing the caller to write the HTTP request to
8883 // the socket. The handshake messages are not processed until Read() is
8884 // called, which then detects that the handshake was aborted, due to the
8885 // peer sending a handshake_failure because it requires a client
8886 // certificate.
8887 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8888 ssl_data2.cert_request_info = cert_request.get();
8889 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8890 net::MockRead data2_reads[] = {
8891 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8892 };
8893 net::StaticSocketDataProvider data2(
8894 data2_reads, arraysize(data2_reads), NULL, 0);
8895 session_deps.socket_factory.AddSocketDataProvider(&data2);
8896
8897 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8898 // the data for the SSL handshake once the TLSv1 connection falls back to
8899 // SSLv3. It has the same behaviour as [ssl_]data2.
8900 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8901 ssl_data3.cert_request_info = cert_request.get();
8902 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8903 net::StaticSocketDataProvider data3(
8904 data2_reads, arraysize(data2_reads), NULL, 0);
8905 session_deps.socket_factory.AddSocketDataProvider(&data3);
8906
8907 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8908 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8909
[email protected]bd0b6772011-01-11 19:59:308910 // Begin the initial SSL handshake.
[email protected]49639fa2011-12-20 23:22:418911 TestCompletionCallback callback;
8912 int rv = trans->Start(&request_info, callback.callback(), net::BoundNetLog());
[email protected]bd0b6772011-01-11 19:59:308913 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8914
8915 // Complete the SSL handshake, which should abort due to requiring a
8916 // client certificate.
8917 rv = callback.WaitForResult();
8918 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8919
8920 // Indicate that no certificate should be supplied. From the perspective
8921 // of SSLClientCertCache, NULL is just as meaningful as a real
8922 // certificate, so this is the same as supply a
8923 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:418924 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]bd0b6772011-01-11 19:59:308925 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8926
8927 // Ensure the certificate was added to the client auth cache before
8928 // allowing the connection to continue restarting.
8929 scoped_refptr<X509Certificate> client_cert;
8930 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8931 &client_cert));
8932 ASSERT_EQ(NULL, client_cert.get());
8933
8934
8935 // Restart the handshake. This will consume ssl_data2, which fails, and
8936 // then consume ssl_data3, which should also fail. The result code is
8937 // checked against what ssl_data3 should return.
8938 rv = callback.WaitForResult();
8939 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8940
8941 // Ensure that the client certificate is removed from the cache on a
8942 // handshake failure.
8943 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8944 &client_cert));
8945}
8946
[email protected]8c405132011-01-11 22:03:188947// Ensure that a client certificate is removed from the SSL client auth
8948// cache when:
8949// 1) An HTTPS proxy is involved.
8950// 3) The HTTPS proxy requests a client certificate.
8951// 4) The client supplies an invalid/unacceptable certificate for the
8952// proxy.
8953// The test is repeated twice, first for connecting to an HTTPS endpoint,
8954// then for connecting to an HTTP endpoint.
8955TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8956 SessionDependencies session_deps(
8957 ProxyService::CreateFixed("https://proxy:70"));
8958 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8959 session_deps.net_log = log.bound().net_log();
8960
8961 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8962 cert_request->host_and_port = "proxy:70";
8963
8964 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8965 // [ssl_]data[1-3]. Rather than represending the endpoint
8966 // (www.example.com:443), they represent failures with the HTTPS proxy
8967 // (proxy:70).
8968 SSLSocketDataProvider ssl_data1(true /* async */,
8969 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8970 ssl_data1.cert_request_info = cert_request.get();
8971 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8972 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8973 session_deps.socket_factory.AddSocketDataProvider(&data1);
8974
8975 SSLSocketDataProvider ssl_data2(true /* async */,
8976 net::ERR_SSL_PROTOCOL_ERROR);
8977 ssl_data2.cert_request_info = cert_request.get();
8978 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8979 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8980 session_deps.socket_factory.AddSocketDataProvider(&data2);
8981
8982 SSLSocketDataProvider ssl_data3(true /* async */,
8983 net::ERR_SSL_PROTOCOL_ERROR);
8984 ssl_data3.cert_request_info = cert_request.get();
8985 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8986 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8987 session_deps.socket_factory.AddSocketDataProvider(&data3);
8988
8989 net::HttpRequestInfo requests[2];
8990 requests[0].url = GURL("https://www.example.com/");
8991 requests[0].method = "GET";
8992 requests[0].load_flags = net::LOAD_NORMAL;
8993
8994 requests[1].url = GURL("http://www.example.com/");
8995 requests[1].method = "GET";
8996 requests[1].load_flags = net::LOAD_NORMAL;
8997
8998 for (size_t i = 0; i < arraysize(requests); ++i) {
8999 session_deps.socket_factory.ResetNextMockIndexes();
9000 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
9001 scoped_ptr<HttpNetworkTransaction> trans(
9002 new HttpNetworkTransaction(session));
9003
9004 // Begin the SSL handshake with the proxy.
[email protected]49639fa2011-12-20 23:22:419005 TestCompletionCallback callback;
9006 int rv = trans->Start(
9007 &requests[i], callback.callback(), net::BoundNetLog());
[email protected]8c405132011-01-11 22:03:189008 ASSERT_EQ(net::ERR_IO_PENDING, rv);
9009
9010 // Complete the SSL handshake, which should abort due to requiring a
9011 // client certificate.
9012 rv = callback.WaitForResult();
9013 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
9014
9015 // Indicate that no certificate should be supplied. From the perspective
9016 // of SSLClientCertCache, NULL is just as meaningful as a real
9017 // certificate, so this is the same as supply a
9018 // legitimate-but-unacceptable certificate.
[email protected]49639fa2011-12-20 23:22:419019 rv = trans->RestartWithCertificate(NULL, callback.callback());
[email protected]8c405132011-01-11 22:03:189020 ASSERT_EQ(net::ERR_IO_PENDING, rv);
9021
9022 // Ensure the certificate was added to the client auth cache before
9023 // allowing the connection to continue restarting.
9024 scoped_refptr<X509Certificate> client_cert;
9025 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
9026 &client_cert));
9027 ASSERT_EQ(NULL, client_cert.get());
9028 // Ensure the certificate was NOT cached for the endpoint. This only
9029 // applies to HTTPS requests, but is fine to check for HTTP requests.
9030 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
9031 &client_cert));
9032
9033 // Restart the handshake. This will consume ssl_data2, which fails, and
9034 // then consume ssl_data3, which should also fail. The result code is
9035 // checked against what ssl_data3 should return.
9036 rv = callback.WaitForResult();
9037 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
9038
9039 // Now that the new handshake has failed, ensure that the client
9040 // certificate was removed from the client auth cache.
9041 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
9042 &client_cert));
9043 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
9044 &client_cert));
9045 }
9046}
9047
[email protected]5c288bc2011-07-26 15:12:059048void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
9049 SpdySessionPoolPeer* pool_peer,
9050 std::string host,
9051 int port,
9052 std::string iplist) {
9053 // Create a host resolver dependency that returns address |iplist| for
9054 // resolutions of |host|.
9055 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:049056
[email protected]5c288bc2011-07-26 15:12:059057 // Setup a HostPortProxyPair.
9058 HostPortPair host_port_pair(host, port);
9059 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
9060 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:049061
[email protected]5c288bc2011-07-26 15:12:059062 // Resolve the host and port.
9063 AddressList addresses;
9064 HostResolver::RequestInfo info(host_port_pair);
[email protected]aa22b242011-11-16 18:58:299065 TestCompletionCallback callback;
9066 int rv = host_resolver->Resolve(info, &addresses, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479067 BoundNetLog());
9068 if (rv == ERR_IO_PENDING)
9069 rv = callback.WaitForResult();
9070 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:049071
[email protected]5c288bc2011-07-26 15:12:059072 // Add the first address as an alias. It would have been better to call
9073 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
9074 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
9075 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
9076 // the |pair|.
9077 const addrinfo* address = addresses.head();
9078 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:049079}
9080
[email protected]e3ceb682011-06-28 23:55:469081TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
9082 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349083 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469084
9085 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
9086 SessionDependencies session_deps;
9087 MockCachingHostResolver host_resolver;
9088 net::HttpNetworkSession::Params params;
9089 params.client_socket_factory = &session_deps.socket_factory;
9090 params.host_resolver = &host_resolver;
9091 params.cert_verifier = session_deps.cert_verifier.get();
9092 params.proxy_service = session_deps.proxy_service.get();
9093 params.ssl_config_service = session_deps.ssl_config_service;
9094 params.http_auth_handler_factory =
9095 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539096 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469097 params.net_log = session_deps.net_log;
9098 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269099 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9100 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469101
9102 SSLSocketDataProvider ssl(true, OK);
9103 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:209104 ssl.next_proto = "spdy/2.1";
[email protected]e3ceb682011-06-28 23:55:469105 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:209106 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]e3ceb682011-06-28 23:55:469107 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9108
9109 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9110 "https://www.google.com", false, 1, LOWEST));
9111 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9112 "https://www.gmail.com", false, 3, LOWEST));
9113 MockWrite spdy_writes[] = {
9114 CreateMockWrite(*host1_req, 1),
9115 CreateMockWrite(*host2_req, 4),
9116 };
9117 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9118 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9119 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9120 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9121 MockRead spdy_reads[] = {
9122 CreateMockRead(*host1_resp, 2),
9123 CreateMockRead(*host1_resp_body, 3),
9124 CreateMockRead(*host2_resp, 5),
9125 CreateMockRead(*host2_resp_body, 6),
9126 MockRead(true, 0, 7),
9127 };
9128
[email protected]a1595312012-01-22 03:25:049129 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:469130 new OrderedSocketData(
9131 spdy_reads, arraysize(spdy_reads),
9132 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:049133 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:469134
[email protected]aa22b242011-11-16 18:58:299135 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469136 HttpRequestInfo request1;
9137 request1.method = "GET";
9138 request1.url = GURL("https://www.google.com/");
9139 request1.load_flags = 0;
9140 HttpNetworkTransaction trans1(session);
9141
[email protected]49639fa2011-12-20 23:22:419142 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469143 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419144 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469145
9146 const HttpResponseInfo* response = trans1.GetResponseInfo();
9147 ASSERT_TRUE(response != NULL);
9148 ASSERT_TRUE(response->headers != NULL);
9149 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9150
9151 std::string response_data;
9152 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9153 EXPECT_EQ("hello!", response_data);
9154
9155 // Preload www.gmail.com into HostCache.
9156 HostPortPair host_port("www.gmail.com", 443);
9157 HostResolver::RequestInfo resolve_info(host_port);
9158 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299159 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479160 BoundNetLog());
9161 EXPECT_EQ(ERR_IO_PENDING, rv);
9162 rv = callback.WaitForResult();
9163 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469164
[email protected]5c288bc2011-07-26 15:12:059165 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9166 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9167 // (www.google.com, 443).
9168 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
9169 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049170
[email protected]e3ceb682011-06-28 23:55:469171 HttpRequestInfo request2;
9172 request2.method = "GET";
9173 request2.url = GURL("https://www.gmail.com/");
9174 request2.load_flags = 0;
9175 HttpNetworkTransaction trans2(session);
9176
[email protected]49639fa2011-12-20 23:22:419177 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469178 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419179 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469180
9181 response = trans2.GetResponseInfo();
9182 ASSERT_TRUE(response != NULL);
9183 ASSERT_TRUE(response->headers != NULL);
9184 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9185 EXPECT_TRUE(response->was_fetched_via_spdy);
9186 EXPECT_TRUE(response->was_npn_negotiated);
9187 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9188 EXPECT_EQ("hello!", response_data);
9189
[email protected]5285d972011-10-18 18:56:349190 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469191 HttpStreamFactory::set_use_alternate_protocols(false);
9192}
9193
9194class OneTimeCachingHostResolver : public net::HostResolver {
9195 public:
9196 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9197 : host_port_(host_port) {}
9198 virtual ~OneTimeCachingHostResolver() {}
9199
9200 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9201
9202 // HostResolver methods:
9203 virtual int Resolve(const RequestInfo& info,
9204 AddressList* addresses,
[email protected]aa22b242011-11-16 18:58:299205 const CompletionCallback& callback,
[email protected]e3ceb682011-06-28 23:55:469206 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:409207 const BoundNetLog& net_log) OVERRIDE {
9208 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:469209 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:409210 }
9211
9212 virtual int ResolveFromCache(const RequestInfo& info,
9213 AddressList* addresses,
9214 const BoundNetLog& net_log) OVERRIDE {
9215 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9216 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]98e1cd012011-11-08 15:33:099217 host_resolver_.GetHostCache()->clear();
[email protected]e3ceb682011-06-28 23:55:469218 return rv;
9219 }
9220
[email protected]95a214c2011-08-04 21:50:409221 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469222 host_resolver_.CancelRequest(req);
9223 }
9224
[email protected]46da33be2011-07-19 21:58:049225 MockCachingHostResolver* GetMockHostResolver() {
9226 return &host_resolver_;
9227 }
9228
[email protected]e3ceb682011-06-28 23:55:469229 private:
9230 MockCachingHostResolver host_resolver_;
9231 const HostPortPair host_port_;
9232};
9233
9234TEST_F(HttpNetworkTransactionTest,
9235 UseIPConnectionPoolingWithHostCacheExpiration) {
9236 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349237 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469238
9239 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9240 SessionDependencies session_deps;
9241 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9242 net::HttpNetworkSession::Params params;
9243 params.client_socket_factory = &session_deps.socket_factory;
9244 params.host_resolver = &host_resolver;
9245 params.cert_verifier = session_deps.cert_verifier.get();
9246 params.proxy_service = session_deps.proxy_service.get();
9247 params.ssl_config_service = session_deps.ssl_config_service;
9248 params.http_auth_handler_factory =
9249 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539250 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469251 params.net_log = session_deps.net_log;
9252 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269253 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9254 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469255
9256 SSLSocketDataProvider ssl(true, OK);
9257 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]1ad77dc2012-01-27 03:51:209258 ssl.next_proto = "spdy/2.1";
[email protected]e3ceb682011-06-28 23:55:469259 ssl.was_npn_negotiated = true;
[email protected]1ad77dc2012-01-27 03:51:209260 ssl.protocol_negotiated = SSLClientSocket::kProtoSPDY21;
[email protected]e3ceb682011-06-28 23:55:469261 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9262
9263 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9264 "https://www.google.com", false, 1, LOWEST));
9265 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9266 "https://www.gmail.com", false, 3, LOWEST));
9267 MockWrite spdy_writes[] = {
9268 CreateMockWrite(*host1_req, 1),
9269 CreateMockWrite(*host2_req, 4),
9270 };
9271 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9272 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9273 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9274 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9275 MockRead spdy_reads[] = {
9276 CreateMockRead(*host1_resp, 2),
9277 CreateMockRead(*host1_resp_body, 3),
9278 CreateMockRead(*host2_resp, 5),
9279 CreateMockRead(*host2_resp_body, 6),
9280 MockRead(true, 0, 7),
9281 };
9282
[email protected]a1595312012-01-22 03:25:049283 scoped_ptr<OrderedSocketData> spdy_data(
[email protected]e3ceb682011-06-28 23:55:469284 new OrderedSocketData(
9285 spdy_reads, arraysize(spdy_reads),
9286 spdy_writes, arraysize(spdy_writes)));
[email protected]a1595312012-01-22 03:25:049287 session_deps.socket_factory.AddSocketDataProvider(spdy_data.get());
[email protected]e3ceb682011-06-28 23:55:469288
[email protected]aa22b242011-11-16 18:58:299289 TestCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469290 HttpRequestInfo request1;
9291 request1.method = "GET";
9292 request1.url = GURL("https://www.google.com/");
9293 request1.load_flags = 0;
9294 HttpNetworkTransaction trans1(session);
9295
[email protected]49639fa2011-12-20 23:22:419296 int rv = trans1.Start(&request1, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469297 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419298 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469299
9300 const HttpResponseInfo* response = trans1.GetResponseInfo();
9301 ASSERT_TRUE(response != NULL);
9302 ASSERT_TRUE(response->headers != NULL);
9303 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9304
9305 std::string response_data;
9306 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9307 EXPECT_EQ("hello!", response_data);
9308
9309 // Preload cache entries into HostCache.
9310 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9311 AddressList ignored;
[email protected]aa22b242011-11-16 18:58:299312 rv = host_resolver.Resolve(resolve_info, &ignored, callback.callback(), NULL,
[email protected]6e78dfb2011-07-28 21:34:479313 BoundNetLog());
9314 EXPECT_EQ(ERR_IO_PENDING, rv);
9315 rv = callback.WaitForResult();
9316 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469317
9318 HttpRequestInfo request2;
9319 request2.method = "GET";
9320 request2.url = GURL("https://www.gmail.com/");
9321 request2.load_flags = 0;
9322 HttpNetworkTransaction trans2(session);
9323
[email protected]5c288bc2011-07-26 15:12:059324 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9325 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9326 // (www.google.com, 443).
9327 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9328 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049329
[email protected]49639fa2011-12-20 23:22:419330 rv = trans2.Start(&request2, callback.callback(), BoundNetLog());
[email protected]e3ceb682011-06-28 23:55:469331 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]49639fa2011-12-20 23:22:419332 EXPECT_EQ(OK, callback.WaitForResult());
[email protected]e3ceb682011-06-28 23:55:469333
9334 response = trans2.GetResponseInfo();
9335 ASSERT_TRUE(response != NULL);
9336 ASSERT_TRUE(response->headers != NULL);
9337 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9338 EXPECT_TRUE(response->was_fetched_via_spdy);
9339 EXPECT_TRUE(response->was_npn_negotiated);
9340 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9341 EXPECT_EQ("hello!", response_data);
9342
[email protected]5285d972011-10-18 18:56:349343 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469344 HttpStreamFactory::set_use_alternate_protocols(false);
9345}
9346
[email protected]5a60c8b2011-10-19 20:14:299347TEST_F(HttpNetworkTransactionTest, ReadPipelineEvictionFallback) {
9348 MockRead data_reads1[] = {
9349 MockRead(false, ERR_PIPELINE_EVICTION),
9350 };
9351 MockRead data_reads2[] = {
9352 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9353 MockRead("hello world"),
9354 MockRead(false, OK),
9355 };
9356 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), NULL, 0);
9357 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), NULL, 0);
9358 StaticSocketDataProvider* data[] = { &data1, &data2 };
9359
9360 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9361
9362 EXPECT_EQ(OK, out.rv);
9363 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9364 EXPECT_EQ("hello world", out.response_data);
9365}
9366
9367TEST_F(HttpNetworkTransactionTest, SendPipelineEvictionFallback) {
9368 MockWrite data_writes1[] = {
9369 MockWrite(false, ERR_PIPELINE_EVICTION),
9370 };
9371 MockWrite data_writes2[] = {
9372 MockWrite("GET / HTTP/1.1\r\n"
9373 "Host: www.google.com\r\n"
9374 "Connection: keep-alive\r\n\r\n"),
9375 };
9376 MockRead data_reads2[] = {
9377 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
9378 MockRead("hello world"),
9379 MockRead(false, OK),
9380 };
9381 StaticSocketDataProvider data1(NULL, 0,
9382 data_writes1, arraysize(data_writes1));
9383 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
9384 data_writes2, arraysize(data_writes2));
9385 StaticSocketDataProvider* data[] = { &data1, &data2 };
9386
9387 SimpleGetHelperResult out = SimpleGetHelperForData(data, arraysize(data));
9388
9389 EXPECT_EQ(OK, out.rv);
9390 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
9391 EXPECT_EQ("hello world", out.response_data);
9392}
9393
[email protected]89ceba9a2009-03-21 03:46:069394} // namespace net