blob: 1de21e77827eb5d5b4decbbc8c587f7742649b16 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]2d731a32010-04-29 01:04:065#include "net/http/http_network_transaction.h"
6
[email protected]77848d12008-11-14 00:00:227#include <math.h> // ceil
[email protected]5285d972011-10-18 18:56:348#include <stdarg.h>
9#include <string>
[email protected]95d88ffe2010-02-04 21:25:3310#include <vector>
[email protected]77848d12008-11-14 00:00:2211
[email protected]2d731a32010-04-29 01:04:0612#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3013#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3314#include "base/file_path.h"
15#include "base/file_util.h"
[email protected]3b63f8f42011-03-28 01:54:1516#include "base/memory/scoped_ptr.h"
[email protected]5e6efa52011-06-27 17:26:4117#include "base/metrics/histogram.h"
[email protected]f36a8132011-09-02 18:36:3318#include "base/test/test_file_util.h"
[email protected]be1ce6a72010-08-03 14:35:2219#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3520#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1221#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3322#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3223#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1224#include "net/base/net_log.h"
25#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3126#include "net/base/request_priority.h"
[email protected]bd0b6772011-01-11 19:59:3027#include "net/base/ssl_cert_request_info.h"
[email protected]db36938c2009-08-19 21:48:4228#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3329#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/base/test_completion_callback.h"
31#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1232#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0033#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2934#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5735#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4036#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5638#include "net/http/http_network_session_peer.h"
[email protected]17291a022011-10-10 07:32:5339#include "net/http/http_server_properties_impl.h"
[email protected]0877e3d2009-10-17 22:29:5740#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3841#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5242#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5343#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1144#include "net/proxy/proxy_resolver.h"
45#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4446#include "net/socket/client_socket_factory.h"
47#include "net/socket/socket_test_util.h"
48#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5449#include "net/spdy/spdy_framer.h"
50#include "net/spdy/spdy_session.h"
51#include "net/spdy/spdy_session_pool.h"
52#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5253#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1554#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5255
56//-----------------------------------------------------------------------------
57
[email protected]13c8a092010-07-29 06:15:4458namespace {
59
60const string16 kBar(ASCIIToUTF16("bar"));
61const string16 kBar2(ASCIIToUTF16("bar2"));
62const string16 kBar3(ASCIIToUTF16("bar3"));
63const string16 kBaz(ASCIIToUTF16("baz"));
64const string16 kFirst(ASCIIToUTF16("first"));
65const string16 kFoo(ASCIIToUTF16("foo"));
66const string16 kFoo2(ASCIIToUTF16("foo2"));
67const string16 kFoo3(ASCIIToUTF16("foo3"));
68const string16 kFou(ASCIIToUTF16("fou"));
69const string16 kSecond(ASCIIToUTF16("second"));
70const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
71const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
72
[email protected]5285d972011-10-18 18:56:3473// MakeNextProtos is a utility function that returns a vector of std::strings
74// from its arguments. Don't forget to terminate the argument list with a NULL.
75std::vector<std::string> MakeNextProtos(const char* a, ...) {
76 std::vector<std::string> ret;
77 ret.push_back(a);
78
79 va_list args;
80 va_start(args, a);
81
82 for (;;) {
83 const char* value = va_arg(args, const char*);
84 if (value == NULL)
85 break;
86 ret.push_back(value);
87 }
88 va_end(args);
89
90 return ret;
91}
92
93// SpdyNextProtos returns a vector of NPN protocol strings for negotiating
94// SPDY.
95std::vector<std::string> SpdyNextProtos() {
96 return MakeNextProtos("http/1.1", "spdy/2", NULL);
97}
98
[email protected]13c8a092010-07-29 06:15:4499} // namespace
100
[email protected]89ceba9a2009-03-21 03:46:06101namespace net {
102
[email protected]e44de5d2009-06-05 20:12:45103// Helper to manage the lifetimes of the dependencies for a
104// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:44105struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:59106 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:42107 SessionDependencies()
108 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:15109 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:02110 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:10111 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08112 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:54113 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:54114 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59115
116 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:45117 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:42118 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:15119 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:42120 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:10121 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:08122 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:54123 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:54124 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:59125
[email protected]73c45322010-10-01 23:57:54126 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:15127 scoped_ptr<CertVerifier> cert_verifier;
[email protected]6104ea5d2011-04-27 21:37:12128 scoped_ptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:42129 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:59130 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50131 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]17291a022011-10-10 07:32:53132 HttpServerPropertiesImpl http_server_properties;
[email protected]a7ea8832010-07-12 17:54:54133 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59134};
135
[email protected]228ff742009-06-05 01:19:59136HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]9e1bdd32011-02-03 21:48:34137 net::HttpNetworkSession::Params params;
138 params.client_socket_factory = &session_deps->socket_factory;
139 params.host_resolver = session_deps->host_resolver.get();
140 params.cert_verifier = session_deps->cert_verifier.get();
[email protected]6104ea5d2011-04-27 21:37:12141 params.proxy_service = session_deps->proxy_service.get();
[email protected]9e1bdd32011-02-03 21:48:34142 params.ssl_config_service = session_deps->ssl_config_service;
143 params.http_auth_handler_factory =
144 session_deps->http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:53145 params.http_server_properties = &session_deps->http_server_properties;
[email protected]9e1bdd32011-02-03 21:48:34146 params.net_log = session_deps->net_log;
147 return new HttpNetworkSession(params);
[email protected]e8d536192008-10-17 22:21:14148}
149
[email protected]89836e22008-09-25 20:33:42150class HttpNetworkTransactionTest : public PlatformTest {
[email protected]e3ceb682011-06-28 23:55:46151 protected:
152 struct SimpleGetHelperResult {
153 int rv;
154 std::string status_line;
155 std::string response_data;
156 };
157
[email protected]2ff8b312010-04-26 22:20:54158 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50159 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
160 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54161 spdy::SpdyFramer::set_enable_compression_default(false);
162 }
163
[email protected]0e75a732008-10-16 20:36:09164 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50165 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
166 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54167 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09168 // Empty the current queue.
169 MessageLoop::current()->RunAllPending();
170 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50171 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
172 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09173 }
174
[email protected]3d2a59b2008-09-26 19:44:25175 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52176
[email protected]31a2bfe2010-02-09 08:03:39177 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
178 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15179 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52180
[email protected]ff007e162009-05-23 09:13:15181 HttpRequestInfo request;
182 request.method = "GET";
183 request.url = GURL("http://www.google.com/");
184 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52185
[email protected]cb9bf6ca2011-01-28 13:15:27186 SessionDependencies session_deps;
187 scoped_ptr<HttpTransaction> trans(
188 new HttpNetworkTransaction(CreateSession(&session_deps)));
189
[email protected]31a2bfe2010-02-09 08:03:39190 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59191 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52192
[email protected]f1f3f0f82011-10-01 20:38:10193 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52194
[email protected]169d0012010-05-10 23:20:12195 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40196 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12197 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15198 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52199
[email protected]ff007e162009-05-23 09:13:15200 out.rv = callback.WaitForResult();
201 if (out.rv != OK)
202 return out;
203
204 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50205 // Can't use ASSERT_* inside helper functions like this, so
206 // return an error.
207 if (response == NULL || response->headers == NULL) {
208 out.rv = ERR_UNEXPECTED;
209 return out;
210 }
[email protected]ff007e162009-05-23 09:13:15211 out.status_line = response->headers->GetStatusLine();
212
[email protected]6d81b482011-02-22 19:47:19213 EXPECT_EQ("192.0.2.33", response->socket_address.host());
214 EXPECT_EQ(0, response->socket_address.port());
215
[email protected]ff007e162009-05-23 09:13:15216 rv = ReadTransaction(trans.get(), &out.response_data);
217 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40218
219 net::CapturingNetLog::EntryList entries;
220 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39221 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40222 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12223 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39224 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40225 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39226 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
227 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15228
[email protected]b2fcd0e2010-12-01 15:19:40229 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40230 NetLogHttpRequestParameter* request_params =
231 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
232 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
233 EXPECT_EQ("Host: www.google.com\r\n"
234 "Connection: keep-alive\r\n\r\n",
235 request_params->GetHeaders().ToString());
236
[email protected]aecfbf22008-10-16 02:02:47237 return out;
[email protected]ff007e162009-05-23 09:13:15238 }
initial.commit586acc5fe2008-07-26 22:42:52239
[email protected]ff007e162009-05-23 09:13:15240 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
241 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52242
[email protected]ff007e162009-05-23 09:13:15243 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15244};
[email protected]231d5a32008-09-13 00:45:27245
[email protected]15a5ccf82008-10-23 19:57:43246// Fill |str| with a long header list that consumes >= |size| bytes.
247void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19248 const char* row =
249 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
250 const int sizeof_row = strlen(row);
251 const int num_rows = static_cast<int>(
252 ceil(static_cast<float>(size) / sizeof_row));
253 const int sizeof_data = num_rows * sizeof_row;
254 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43255 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51256
[email protected]4ddaf2502008-10-23 18:26:19257 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43258 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19259}
260
[email protected]385a4672009-03-11 22:21:29261// Alternative functions that eliminate randomness and dependency on the local
262// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20263void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29264 static const uint8 bytes[] = {
265 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
266 };
267 static size_t current_byte = 0;
268 for (size_t i = 0; i < n; ++i) {
269 output[i] = bytes[current_byte++];
270 current_byte %= arraysize(bytes);
271 }
272}
273
[email protected]fe2bc6a2009-03-23 16:52:20274void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29275 static const uint8 bytes[] = {
276 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
277 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
278 };
279 static size_t current_byte = 0;
280 for (size_t i = 0; i < n; ++i) {
281 output[i] = bytes[current_byte++];
282 current_byte %= arraysize(bytes);
283 }
284}
285
[email protected]fe2bc6a2009-03-23 16:52:20286std::string MockGetHostName() {
287 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29288}
289
[email protected]e60e47a2010-07-14 03:37:18290template<typename ParentPool>
291class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31292 public:
[email protected]9e1bdd32011-02-03 21:48:34293 CaptureGroupNameSocketPool(HostResolver* host_resolver,
294 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18295
[email protected]d80a4322009-08-14 07:07:49296 const std::string last_group_name_received() const {
297 return last_group_name_;
298 }
299
[email protected]684970b2009-08-14 04:54:46300 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49301 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31302 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31303 ClientSocketHandle* handle,
[email protected]f1f3f0f82011-10-01 20:38:10304 OldCompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53305 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31306 last_group_name_ = group_name;
307 return ERR_IO_PENDING;
308 }
[email protected]04e5be32009-06-26 20:00:31309 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21310 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31311 virtual void ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10312 StreamSocket* socket,
[email protected]9f95c692011-02-11 19:20:19313 int id) {}
[email protected]04e5be32009-06-26 20:00:31314 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31315 virtual int IdleSocketCount() const {
316 return 0;
317 }
318 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
319 return 0;
320 }
321 virtual LoadState GetLoadState(const std::string& group_name,
322 const ClientSocketHandle* handle) const {
323 return LOAD_STATE_IDLE;
324 }
[email protected]a796bcec2010-03-22 17:17:26325 virtual base::TimeDelta ConnectionTimeout() const {
326 return base::TimeDelta();
327 }
[email protected]d80a4322009-08-14 07:07:49328
329 private:
[email protected]04e5be32009-06-26 20:00:31330 std::string last_group_name_;
331};
332
[email protected]ab739042011-04-07 15:22:28333typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
334CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13335typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
336CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06337typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11338CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18339typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
340CaptureGroupNameSSLSocketPool;
341
342template<typename ParentPool>
343CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34344 HostResolver* host_resolver,
345 CertVerifier* /* cert_verifier */)
346 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18347
348template<>
[email protected]2df19bb2010-08-25 20:13:46349CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34350 HostResolver* host_resolver,
351 CertVerifier* /* cert_verifier */)
352 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
[email protected]2df19bb2010-08-25 20:13:46353
354template<>
[email protected]e60e47a2010-07-14 03:37:18355CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34356 HostResolver* host_resolver,
357 CertVerifier* cert_verifier)
358 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
[email protected]feb79bcd2011-07-21 16:55:17359 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11360
[email protected]231d5a32008-09-13 00:45:27361//-----------------------------------------------------------------------------
362
[email protected]dae22c52010-07-30 02:16:35363// This is the expected return from a current server advertising SPDY.
364static const char kAlternateProtocolHttpHeader[] =
365 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
366
[email protected]79cb5c12011-09-12 13:12:04367// Helper functions for validating that AuthChallengeInfo's are correctly
368// configured for common cases.
369bool CheckBasicServerAuth(const AuthChallengeInfo* auth_challenge) {
370 if (!auth_challenge)
371 return false;
372 EXPECT_FALSE(auth_challenge->is_proxy);
373 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
374 EXPECT_EQ("MyRealm1", auth_challenge->realm);
375 EXPECT_EQ("basic", auth_challenge->scheme);
376 return true;
377}
378
379bool CheckBasicProxyAuth(const AuthChallengeInfo* auth_challenge) {
380 if (!auth_challenge)
381 return false;
382 EXPECT_TRUE(auth_challenge->is_proxy);
383 EXPECT_EQ("myproxy:70", auth_challenge->challenger.ToString());
384 EXPECT_EQ("MyRealm1", auth_challenge->realm);
385 EXPECT_EQ("basic", auth_challenge->scheme);
386 return true;
387}
388
389bool CheckDigestServerAuth(const AuthChallengeInfo* auth_challenge) {
390 if (!auth_challenge)
391 return false;
392 EXPECT_FALSE(auth_challenge->is_proxy);
393 EXPECT_EQ("www.google.com:80", auth_challenge->challenger.ToString());
394 EXPECT_EQ("digestive", auth_challenge->realm);
395 EXPECT_EQ("digest", auth_challenge->scheme);
396 return true;
397}
398
399bool CheckNTLMServerAuth(const AuthChallengeInfo* auth_challenge) {
400 if (!auth_challenge)
401 return false;
402 EXPECT_FALSE(auth_challenge->is_proxy);
403 EXPECT_EQ("172.22.68.17:80", auth_challenge->challenger.ToString());
404 EXPECT_EQ(std::string(), auth_challenge->realm);
405 EXPECT_EQ("ntlm", auth_challenge->scheme);
406 return true;
407}
408
[email protected]231d5a32008-09-13 00:45:27409TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59410 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40411 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43412 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27413}
414
415TEST_F(HttpNetworkTransactionTest, SimpleGET) {
416 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35417 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
418 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42419 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27420 };
[email protected]31a2bfe2010-02-09 08:03:39421 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
422 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42423 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27424 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
425 EXPECT_EQ("hello world", out.response_data);
426}
427
428// Response with no status line.
429TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
430 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35431 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42432 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27433 };
[email protected]31a2bfe2010-02-09 08:03:39434 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
435 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42436 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27437 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
438 EXPECT_EQ("hello world", out.response_data);
439}
440
441// Allow up to 4 bytes of junk to precede status line.
442TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
443 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35444 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42445 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27446 };
[email protected]31a2bfe2010-02-09 08:03:39447 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
448 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42449 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27450 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
451 EXPECT_EQ("DATA", out.response_data);
452}
453
454// Allow up to 4 bytes of junk to precede status line.
455TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
456 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35457 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42458 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27459 };
[email protected]31a2bfe2010-02-09 08:03:39460 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
461 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42462 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27463 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
464 EXPECT_EQ("DATA", out.response_data);
465}
466
467// Beyond 4 bytes of slop and it should fail to find a status line.
468TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
469 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35470 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42471 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27472 };
[email protected]31a2bfe2010-02-09 08:03:39473 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
474 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42475 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25476 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
477 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27478}
479
480// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
481TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
482 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35483 MockRead("\n"),
484 MockRead("\n"),
485 MockRead("Q"),
486 MockRead("J"),
487 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42488 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27489 };
[email protected]31a2bfe2010-02-09 08:03:39490 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
491 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42492 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27493 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
494 EXPECT_EQ("DATA", out.response_data);
495}
496
497// Close the connection before enough bytes to have a status line.
498TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
499 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35500 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42501 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27502 };
[email protected]31a2bfe2010-02-09 08:03:39503 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
504 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42505 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27506 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
507 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52508}
509
[email protected]f9d44aa2008-09-23 23:57:17510// Simulate a 204 response, lacking a Content-Length header, sent over a
511// persistent connection. The response should still terminate since a 204
512// cannot have a response body.
513TEST_F(HttpNetworkTransactionTest, StopsReading204) {
514 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35515 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
516 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42517 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17518 };
[email protected]31a2bfe2010-02-09 08:03:39519 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
520 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42521 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17522 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
523 EXPECT_EQ("", out.response_data);
524}
525
[email protected]0877e3d2009-10-17 22:29:57526// A simple request using chunked encoding with some extra data after.
527// (Like might be seen in a pipelined response.)
528TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
529 MockRead data_reads[] = {
530 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
531 MockRead("5\r\nHello\r\n"),
532 MockRead("1\r\n"),
533 MockRead(" \r\n"),
534 MockRead("5\r\nworld\r\n"),
535 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
536 MockRead(false, OK),
537 };
[email protected]31a2bfe2010-02-09 08:03:39538 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
539 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57540 EXPECT_EQ(OK, out.rv);
541 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
542 EXPECT_EQ("Hello world", out.response_data);
543}
544
[email protected]9fe44f52010-09-23 18:36:00545// Next tests deal with http://crbug.com/56344.
546
547TEST_F(HttpNetworkTransactionTest,
548 MultipleContentLengthHeadersNoTransferEncoding) {
549 MockRead data_reads[] = {
550 MockRead("HTTP/1.1 200 OK\r\n"),
551 MockRead("Content-Length: 10\r\n"),
552 MockRead("Content-Length: 5\r\n\r\n"),
553 };
554 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
555 arraysize(data_reads));
556 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
557}
558
559TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04560 DuplicateContentLengthHeadersNoTransferEncoding) {
561 MockRead data_reads[] = {
562 MockRead("HTTP/1.1 200 OK\r\n"),
563 MockRead("Content-Length: 5\r\n"),
564 MockRead("Content-Length: 5\r\n\r\n"),
565 MockRead("Hello"),
566 };
567 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
568 arraysize(data_reads));
569 EXPECT_EQ(OK, out.rv);
570 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
571 EXPECT_EQ("Hello", out.response_data);
572}
573
574TEST_F(HttpNetworkTransactionTest,
575 ComplexContentLengthHeadersNoTransferEncoding) {
576 // More than 2 dupes.
577 {
578 MockRead data_reads[] = {
579 MockRead("HTTP/1.1 200 OK\r\n"),
580 MockRead("Content-Length: 5\r\n"),
581 MockRead("Content-Length: 5\r\n"),
582 MockRead("Content-Length: 5\r\n\r\n"),
583 MockRead("Hello"),
584 };
585 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
586 arraysize(data_reads));
587 EXPECT_EQ(OK, out.rv);
588 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
589 EXPECT_EQ("Hello", out.response_data);
590 }
591 // HTTP/1.0
592 {
593 MockRead data_reads[] = {
594 MockRead("HTTP/1.0 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.0 200 OK", out.status_line);
604 EXPECT_EQ("Hello", out.response_data);
605 }
606 // 2 dupes and one mismatched.
607 {
608 MockRead data_reads[] = {
609 MockRead("HTTP/1.1 200 OK\r\n"),
610 MockRead("Content-Length: 10\r\n"),
611 MockRead("Content-Length: 10\r\n"),
612 MockRead("Content-Length: 5\r\n\r\n"),
613 };
614 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
615 arraysize(data_reads));
616 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
617 }
618}
619
620TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00621 MultipleContentLengthHeadersTransferEncoding) {
622 MockRead data_reads[] = {
623 MockRead("HTTP/1.1 200 OK\r\n"),
624 MockRead("Content-Length: 666\r\n"),
625 MockRead("Content-Length: 1337\r\n"),
626 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
627 MockRead("5\r\nHello\r\n"),
628 MockRead("1\r\n"),
629 MockRead(" \r\n"),
630 MockRead("5\r\nworld\r\n"),
631 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
632 MockRead(false, OK),
633 };
634 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
635 arraysize(data_reads));
636 EXPECT_EQ(OK, out.rv);
637 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
638 EXPECT_EQ("Hello world", out.response_data);
639}
640
[email protected]1628fe92011-10-04 23:04:55641// Next tests deal with http://crbug.com/98895.
642
643// Checks that a single Content-Disposition header results in no error.
644TEST_F(HttpNetworkTransactionTest, SingleContentDispositionHeader) {
645 MockRead data_reads[] = {
646 MockRead("HTTP/1.1 200 OK\r\n"),
647 MockRead("Content-Disposition: attachment;filename=\"salutations.txt\"r\n"),
648 MockRead("Content-Length: 5\r\n\r\n"),
649 MockRead("Hello"),
650 };
651 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
652 arraysize(data_reads));
653 EXPECT_EQ(OK, out.rv);
654 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
655 EXPECT_EQ("Hello", out.response_data);
656}
657
658// Checks that two identical Content-Disposition headers result in an error.
659TEST_F(HttpNetworkTransactionTest,
660 DuplicateIdenticalContentDispositionHeaders) {
661 MockRead data_reads[] = {
662 MockRead("HTTP/1.1 200 OK\r\n"),
663 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
664 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
665 MockRead("Content-Length: 5\r\n\r\n"),
666 MockRead("Hello"),
667 };
668 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
669 arraysize(data_reads));
670 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
671}
672
673// Checks that two distinct Content-Disposition headers result in an error.
674TEST_F(HttpNetworkTransactionTest, DuplicateDistinctContentDispositionHeaders) {
675 MockRead data_reads[] = {
676 MockRead("HTTP/1.1 200 OK\r\n"),
677 MockRead("Content-Disposition: attachment;filename=\"greetings.txt\"r\n"),
678 MockRead("Content-Disposition: attachment;filename=\"hi.txt\"r\n"),
679 MockRead("Content-Length: 5\r\n\r\n"),
680 MockRead("Hello"),
681 };
682 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
683 arraysize(data_reads));
684 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION, out.rv);
685}
686
687// Checks the behavior of a single Location header.
688TEST_F(HttpNetworkTransactionTest, SingleLocationHeader) {
689 MockRead data_reads[] = {
690 MockRead("HTTP/1.1 302 Redirect\r\n"),
691 MockRead("Location: http://good.com/\r\n"),
692 MockRead("Content-Length: 0\r\n\r\n"),
693 MockRead(false, OK),
694 };
695
696 HttpRequestInfo request;
697 request.method = "GET";
698 request.url = GURL("http://redirect.com/");
699 request.load_flags = 0;
700
701 SessionDependencies session_deps;
702 scoped_ptr<HttpTransaction> trans(
703 new HttpNetworkTransaction(CreateSession(&session_deps)));
704
705 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
706 session_deps.socket_factory.AddSocketDataProvider(&data);
707
708 TestOldCompletionCallback callback;
709
710 int rv = trans->Start(&request, &callback, BoundNetLog());
711 EXPECT_EQ(ERR_IO_PENDING, rv);
712
713 EXPECT_EQ(OK, callback.WaitForResult());
714
715 const HttpResponseInfo* response = trans->GetResponseInfo();
716 ASSERT_TRUE(response != NULL && response->headers != NULL);
717 EXPECT_EQ("HTTP/1.1 302 Redirect", response->headers->GetStatusLine());
718 std::string url;
719 EXPECT_TRUE(response->headers->IsRedirect(&url));
720 EXPECT_EQ("http://good.com/", url);
721}
722
723// Checks that two identical Location headers result in an error.
724TEST_F(HttpNetworkTransactionTest, DuplicateIdenticalLocationHeaders) {
725 MockRead data_reads[] = {
726 MockRead("HTTP/1.1 302 Redirect\r\n"),
727 MockRead("Location: http://good.com/\r\n"),
728 MockRead("Location: http://good.com/\r\n"),
729 MockRead("Content-Length: 0\r\n\r\n"),
730 MockRead(false, OK),
731 };
732 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
733 arraysize(data_reads));
734 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
735}
736
737// Checks that two distinct Location headers result in an error.
738TEST_F(HttpNetworkTransactionTest, DuplicateDistinctLocationHeaders) {
739 MockRead data_reads[] = {
740 MockRead("HTTP/1.1 302 Redirect\r\n"),
741 MockRead("Location: http://good.com/\r\n"),
742 MockRead("Location: http://evil.com/\r\n"),
743 MockRead("Content-Length: 0\r\n\r\n"),
744 MockRead(false, OK),
745 };
746 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
747 arraysize(data_reads));
748 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_LOCATION, out.rv);
749}
750
[email protected]ef0faf2e72009-03-05 23:27:23751// Do a request using the HEAD method. Verify that we don't try to read the
752// message body (since HEAD has none).
753TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42754 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23755 request.method = "HEAD";
756 request.url = GURL("http://www.google.com/");
757 request.load_flags = 0;
758
[email protected]cb9bf6ca2011-01-28 13:15:27759 SessionDependencies session_deps;
760 scoped_ptr<HttpTransaction> trans(
761 new HttpNetworkTransaction(CreateSession(&session_deps)));
762
[email protected]ef0faf2e72009-03-05 23:27:23763 MockWrite data_writes1[] = {
764 MockWrite("HEAD / HTTP/1.1\r\n"
765 "Host: www.google.com\r\n"
766 "Connection: keep-alive\r\n"
767 "Content-Length: 0\r\n\r\n"),
768 };
769 MockRead data_reads1[] = {
770 MockRead("HTTP/1.1 404 Not Found\r\n"),
771 MockRead("Server: Blah\r\n"),
772 MockRead("Content-Length: 1234\r\n\r\n"),
773
774 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42775 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23776 };
777
[email protected]31a2bfe2010-02-09 08:03:39778 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
779 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59780 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23781
[email protected]f1f3f0f82011-10-01 20:38:10782 TestOldCompletionCallback callback1;
[email protected]ef0faf2e72009-03-05 23:27:23783
[email protected]5a1d7ca2010-04-28 20:12:27784 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42785 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23786
787 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42788 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23789
[email protected]1c773ea12009-04-28 19:58:42790 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50791 ASSERT_TRUE(response != NULL);
[email protected]ef0faf2e72009-03-05 23:27:23792
793 // Check that the headers got parsed.
794 EXPECT_TRUE(response->headers != NULL);
795 EXPECT_EQ(1234, response->headers->GetContentLength());
796 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
797
798 std::string server_header;
799 void* iter = NULL;
800 bool has_server_header = response->headers->EnumerateHeader(
801 &iter, "Server", &server_header);
802 EXPECT_TRUE(has_server_header);
803 EXPECT_EQ("Blah", server_header);
804
805 // Reading should give EOF right away, since there is no message body
806 // (despite non-zero content-length).
807 std::string response_data;
808 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42809 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23810 EXPECT_EQ("", response_data);
811}
812
initial.commit586acc5fe2008-07-26 22:42:52813TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59814 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27815 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52816
817 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35818 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
819 MockRead("hello"),
820 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
821 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42822 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52823 };
[email protected]31a2bfe2010-02-09 08:03:39824 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59825 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52826
[email protected]0b0bf032010-09-21 18:08:50827 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52828 "hello", "world"
829 };
830
831 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42832 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52833 request.method = "GET";
834 request.url = GURL("http://www.google.com/");
835 request.load_flags = 0;
836
[email protected]cb9bf6ca2011-01-28 13:15:27837 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
838
[email protected]f1f3f0f82011-10-01 20:38:10839 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52840
[email protected]5a1d7ca2010-04-28 20:12:27841 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42842 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52843
844 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42845 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52846
[email protected]1c773ea12009-04-28 19:58:42847 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50848 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52849
850 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25851 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52852
853 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57854 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42855 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25856 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52857 }
858}
859
860TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42861 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52862 request.method = "POST";
863 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42864 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52865 request.upload_data->AppendBytes("foo", 3);
866 request.load_flags = 0;
867
[email protected]cb9bf6ca2011-01-28 13:15:27868 SessionDependencies session_deps;
869 scoped_ptr<HttpTransaction> trans(
870 new HttpNetworkTransaction(CreateSession(&session_deps)));
871
initial.commit586acc5fe2008-07-26 22:42:52872 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35873 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
874 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
875 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42876 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52877 };
[email protected]31a2bfe2010-02-09 08:03:39878 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59879 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52880
[email protected]f1f3f0f82011-10-01 20:38:10881 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52882
[email protected]5a1d7ca2010-04-28 20:12:27883 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42884 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52885
886 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42887 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52888
[email protected]1c773ea12009-04-28 19:58:42889 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50890 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:52891
892 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25893 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52894
895 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57896 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42897 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25898 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52899}
900
[email protected]3a2d3662009-03-27 03:49:14901// This test is almost the same as Ignores100 above, but the response contains
902// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57903// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14904TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42905 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14906 request.method = "GET";
907 request.url = GURL("http://www.foo.com/");
908 request.load_flags = 0;
909
[email protected]cb9bf6ca2011-01-28 13:15:27910 SessionDependencies session_deps;
911 scoped_ptr<HttpTransaction> trans(
912 new HttpNetworkTransaction(CreateSession(&session_deps)));
913
[email protected]3a2d3662009-03-27 03:49:14914 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57915 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
916 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14917 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42918 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14919 };
[email protected]31a2bfe2010-02-09 08:03:39920 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59921 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14922
[email protected]f1f3f0f82011-10-01 20:38:10923 TestOldCompletionCallback callback;
[email protected]3a2d3662009-03-27 03:49:14924
[email protected]5a1d7ca2010-04-28 20:12:27925 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42926 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14927
928 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42929 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14930
[email protected]1c773ea12009-04-28 19:58:42931 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:50932 ASSERT_TRUE(response != NULL);
[email protected]3a2d3662009-03-27 03:49:14933
934 EXPECT_TRUE(response->headers != NULL);
935 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
936
937 std::string response_data;
938 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42939 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14940 EXPECT_EQ("hello world", response_data);
941}
942
[email protected]ee9410e72010-01-07 01:42:38943TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38944 HttpRequestInfo request;
945 request.method = "POST";
946 request.url = GURL("http://www.foo.com/");
947 request.load_flags = 0;
948
[email protected]cb9bf6ca2011-01-28 13:15:27949 SessionDependencies session_deps;
950 scoped_ptr<HttpTransaction> trans(
951 new HttpNetworkTransaction(CreateSession(&session_deps)));
952
[email protected]ee9410e72010-01-07 01:42:38953 MockRead data_reads[] = {
954 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
955 MockRead(true, 0),
956 };
[email protected]31a2bfe2010-02-09 08:03:39957 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38958 session_deps.socket_factory.AddSocketDataProvider(&data);
959
[email protected]f1f3f0f82011-10-01 20:38:10960 TestOldCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:38961
[email protected]5a1d7ca2010-04-28 20:12:27962 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38963 EXPECT_EQ(ERR_IO_PENDING, rv);
964
965 rv = callback.WaitForResult();
966 EXPECT_EQ(OK, rv);
967
968 std::string response_data;
969 rv = ReadTransaction(trans.get(), &response_data);
970 EXPECT_EQ(OK, rv);
971 EXPECT_EQ("", response_data);
972}
973
974TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38975 HttpRequestInfo request;
976 request.method = "POST";
977 request.url = GURL("http://www.foo.com/");
978 request.load_flags = 0;
979
[email protected]cb9bf6ca2011-01-28 13:15:27980 SessionDependencies session_deps;
981 scoped_ptr<HttpTransaction> trans(
982 new HttpNetworkTransaction(CreateSession(&session_deps)));
983
[email protected]ee9410e72010-01-07 01:42:38984 MockRead data_reads[] = {
985 MockRead(true, 0),
986 };
[email protected]31a2bfe2010-02-09 08:03:39987 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38988 session_deps.socket_factory.AddSocketDataProvider(&data);
989
[email protected]f1f3f0f82011-10-01 20:38:10990 TestOldCompletionCallback callback;
[email protected]ee9410e72010-01-07 01:42:38991
[email protected]5a1d7ca2010-04-28 20:12:27992 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38993 EXPECT_EQ(ERR_IO_PENDING, rv);
994
995 rv = callback.WaitForResult();
996 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
997}
998
[email protected]3d2a59b2008-09-26 19:44:25999// read_failure specifies a read failure that should cause the network
1000// transaction to resend the request.
1001void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
1002 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:421003 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:521004 request.method = "GET";
1005 request.url = GURL("http://www.foo.com/");
1006 request.load_flags = 0;
1007
[email protected]cb9bf6ca2011-01-28 13:15:271008 SessionDependencies session_deps;
1009 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1010
initial.commit586acc5fe2008-07-26 22:42:521011 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:351012 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1013 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:251014 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:521015 };
[email protected]31a2bfe2010-02-09 08:03:391016 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591017 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:521018
1019 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:351020 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1021 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:421022 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:521023 };
[email protected]31a2bfe2010-02-09 08:03:391024 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591025 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:521026
1027 const char* kExpectedResponseData[] = {
1028 "hello", "world"
1029 };
1030
1031 for (int i = 0; i < 2; ++i) {
[email protected]f1f3f0f82011-10-01 20:38:101032 TestOldCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:521033
[email protected]5695b8c2009-09-30 21:36:431034 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:521035
[email protected]5a1d7ca2010-04-28 20:12:271036 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421037 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:521038
1039 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421040 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:521041
[email protected]1c773ea12009-04-28 19:58:421042 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501043 ASSERT_TRUE(response != NULL);
initial.commit586acc5fe2008-07-26 22:42:521044
1045 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:251046 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:521047
1048 std::string response_data;
[email protected]af4876d2008-10-21 23:10:571049 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421050 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:251051 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:521052 }
1053}
[email protected]3d2a59b2008-09-26 19:44:251054
1055TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421056 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:251057 KeepAliveConnectionResendRequestTest(read_failure);
1058}
1059
1060TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:421061 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:251062 KeepAliveConnectionResendRequestTest(read_failure);
1063}
1064
1065TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:421066 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:251067 request.method = "GET";
1068 request.url = GURL("http://www.google.com/");
1069 request.load_flags = 0;
1070
[email protected]cb9bf6ca2011-01-28 13:15:271071 SessionDependencies session_deps;
1072 scoped_ptr<HttpTransaction> trans(
1073 new HttpNetworkTransaction(CreateSession(&session_deps)));
1074
[email protected]3d2a59b2008-09-26 19:44:251075 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421076 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:351077 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1078 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:421079 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:251080 };
[email protected]31a2bfe2010-02-09 08:03:391081 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591082 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:251083
[email protected]f1f3f0f82011-10-01 20:38:101084 TestOldCompletionCallback callback;
[email protected]3d2a59b2008-09-26 19:44:251085
[email protected]5a1d7ca2010-04-28 20:12:271086 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421087 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:251088
1089 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421090 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:251091
[email protected]1c773ea12009-04-28 19:58:421092 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:251093 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:251094}
1095
1096// What do various browsers do when the server closes a non-keepalive
1097// connection without sending any response header or body?
1098//
1099// IE7: error page
1100// Safari 3.1.2 (Windows): error page
1101// Firefox 3.0.1: blank page
1102// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:421103// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
1104// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:251105TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
1106 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:421107 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:351108 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
1109 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:421110 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:251111 };
[email protected]31a2bfe2010-02-09 08:03:391112 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
1113 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:421114 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:251115}
[email protected]038e9a32008-10-08 22:40:161116
[email protected]0b0bf032010-09-21 18:08:501117// Test that we correctly reuse a keep-alive connection after not explicitly
1118// reading the body.
1119TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:131120 HttpRequestInfo request;
1121 request.method = "GET";
1122 request.url = GURL("http://www.foo.com/");
1123 request.load_flags = 0;
1124
[email protected]cb9bf6ca2011-01-28 13:15:271125 SessionDependencies session_deps;
1126 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1127
[email protected]0b0bf032010-09-21 18:08:501128 // Note that because all these reads happen in the same
1129 // StaticSocketDataProvider, it shows that the same socket is being reused for
1130 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:131131 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:501132 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
1133 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:131134 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:501135 MockRead("HTTP/1.1 302 Found\r\n"
1136 "Content-Length: 0\r\n\r\n"),
1137 MockRead("HTTP/1.1 302 Found\r\n"
1138 "Content-Length: 5\r\n\r\n"
1139 "hello"),
1140 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1141 "Content-Length: 0\r\n\r\n"),
1142 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
1143 "Content-Length: 5\r\n\r\n"
1144 "hello"),
[email protected]fc31d6a42010-06-24 18:05:131145 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
1146 MockRead("hello"),
1147 };
1148 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
1149 session_deps.socket_factory.AddSocketDataProvider(&data1);
1150
1151 MockRead data2_reads[] = {
1152 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
1153 };
1154 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
1155 session_deps.socket_factory.AddSocketDataProvider(&data2);
1156
[email protected]0b0bf032010-09-21 18:08:501157 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
1158 std::string response_lines[kNumUnreadBodies];
1159
1160 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]f1f3f0f82011-10-01 20:38:101161 TestOldCompletionCallback callback;
[email protected]fc31d6a42010-06-24 18:05:131162
1163 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1164
1165 int rv = trans->Start(&request, &callback, BoundNetLog());
1166 EXPECT_EQ(ERR_IO_PENDING, rv);
1167
1168 rv = callback.WaitForResult();
1169 EXPECT_EQ(OK, rv);
1170
1171 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:501172 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:131173
[email protected]0b0bf032010-09-21 18:08:501174 ASSERT_TRUE(response->headers != NULL);
1175 response_lines[i] = response->headers->GetStatusLine();
1176
1177 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:131178 }
[email protected]0b0bf032010-09-21 18:08:501179
1180 const char* const kStatusLines[] = {
1181 "HTTP/1.1 204 No Content",
1182 "HTTP/1.1 205 Reset Content",
1183 "HTTP/1.1 304 Not Modified",
1184 "HTTP/1.1 302 Found",
1185 "HTTP/1.1 302 Found",
1186 "HTTP/1.1 301 Moved Permanently",
1187 "HTTP/1.1 301 Moved Permanently",
1188 };
1189
1190 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1191 forgot_to_update_kStatusLines);
1192
1193 for (int i = 0; i < kNumUnreadBodies; ++i)
1194 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1195
[email protected]f1f3f0f82011-10-01 20:38:101196 TestOldCompletionCallback callback;
[email protected]0b0bf032010-09-21 18:08:501197 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1198 int rv = trans->Start(&request, &callback, BoundNetLog());
1199 EXPECT_EQ(ERR_IO_PENDING, rv);
1200 rv = callback.WaitForResult();
1201 EXPECT_EQ(OK, rv);
1202 const HttpResponseInfo* response = trans->GetResponseInfo();
1203 ASSERT_TRUE(response != NULL);
1204 ASSERT_TRUE(response->headers != NULL);
1205 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1206 std::string response_data;
1207 rv = ReadTransaction(trans.get(), &response_data);
1208 EXPECT_EQ(OK, rv);
1209 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131210}
1211
[email protected]038e9a32008-10-08 22:40:161212// Test the request-challenge-retry sequence for basic auth.
1213// (basic auth is the easiest to mock, because it has no randomness).
1214TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421215 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161216 request.method = "GET";
1217 request.url = GURL("http://www.google.com/");
1218 request.load_flags = 0;
1219
[email protected]cb9bf6ca2011-01-28 13:15:271220 SessionDependencies session_deps;
1221 scoped_ptr<HttpTransaction> trans(
1222 new HttpNetworkTransaction(CreateSession(&session_deps)));
1223
[email protected]f9ee6b52008-11-08 06:46:231224 MockWrite data_writes1[] = {
1225 MockWrite("GET / HTTP/1.1\r\n"
1226 "Host: www.google.com\r\n"
1227 "Connection: keep-alive\r\n\r\n"),
1228 };
1229
[email protected]038e9a32008-10-08 22:40:161230 MockRead data_reads1[] = {
1231 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1232 // Give a couple authenticate options (only the middle one is actually
1233 // supported).
[email protected]22927ad2009-09-21 19:56:191234 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161235 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1236 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1237 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1238 // Large content-length -- won't matter, as connection will be reset.
1239 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421240 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161241 };
1242
1243 // After calling trans->RestartWithAuth(), this is the request we should
1244 // be issuing -- the final header line contains the credentials.
1245 MockWrite data_writes2[] = {
1246 MockWrite("GET / HTTP/1.1\r\n"
1247 "Host: www.google.com\r\n"
1248 "Connection: keep-alive\r\n"
1249 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1250 };
1251
1252 // Lastly, the server responds with the actual content.
1253 MockRead data_reads2[] = {
1254 MockRead("HTTP/1.0 200 OK\r\n"),
1255 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1256 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421257 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161258 };
1259
[email protected]31a2bfe2010-02-09 08:03:391260 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1261 data_writes1, arraysize(data_writes1));
1262 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1263 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591264 session_deps.socket_factory.AddSocketDataProvider(&data1);
1265 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161266
[email protected]f1f3f0f82011-10-01 20:38:101267 TestOldCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:161268
[email protected]5a1d7ca2010-04-28 20:12:271269 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421270 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161271
1272 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421273 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161274
[email protected]1c773ea12009-04-28 19:58:421275 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501276 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041277 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:161278
[email protected]f1f3f0f82011-10-01 20:38:101279 TestOldCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:161280
[email protected]13c8a092010-07-29 06:15:441281 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421282 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161283
1284 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421285 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161286
1287 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501288 ASSERT_TRUE(response != NULL);
[email protected]038e9a32008-10-08 22:40:161289 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1290 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161291}
1292
[email protected]861fcd52009-08-26 02:33:461293TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461294 HttpRequestInfo request;
1295 request.method = "GET";
1296 request.url = GURL("http://www.google.com/");
1297 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1298
[email protected]cb9bf6ca2011-01-28 13:15:271299 SessionDependencies session_deps;
1300 scoped_ptr<HttpTransaction> trans(
1301 new HttpNetworkTransaction(CreateSession(&session_deps)));
1302
[email protected]861fcd52009-08-26 02:33:461303 MockWrite data_writes[] = {
1304 MockWrite("GET / HTTP/1.1\r\n"
1305 "Host: www.google.com\r\n"
1306 "Connection: keep-alive\r\n\r\n"),
1307 };
1308
1309 MockRead data_reads[] = {
1310 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1311 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1312 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1313 // Large content-length -- won't matter, as connection will be reset.
1314 MockRead("Content-Length: 10000\r\n\r\n"),
1315 MockRead(false, ERR_FAILED),
1316 };
1317
[email protected]31a2bfe2010-02-09 08:03:391318 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1319 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591320 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f1f3f0f82011-10-01 20:38:101321 TestOldCompletionCallback callback;
[email protected]861fcd52009-08-26 02:33:461322
[email protected]5a1d7ca2010-04-28 20:12:271323 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461324 EXPECT_EQ(ERR_IO_PENDING, rv);
1325
1326 rv = callback.WaitForResult();
1327 EXPECT_EQ(0, rv);
1328
1329 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501330 ASSERT_TRUE(response != NULL);
[email protected]861fcd52009-08-26 02:33:461331 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1332}
1333
[email protected]2d2697f92009-02-18 21:00:321334// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1335// connection.
1336TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421337 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321338 request.method = "GET";
1339 request.url = GURL("http://www.google.com/");
1340 request.load_flags = 0;
1341
[email protected]cb9bf6ca2011-01-28 13:15:271342 SessionDependencies session_deps;
1343 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1344
[email protected]2d2697f92009-02-18 21:00:321345 MockWrite data_writes1[] = {
1346 MockWrite("GET / HTTP/1.1\r\n"
1347 "Host: www.google.com\r\n"
1348 "Connection: keep-alive\r\n\r\n"),
1349
1350 // After calling trans->RestartWithAuth(), this is the request we should
1351 // be issuing -- the final header line contains the credentials.
1352 MockWrite("GET / HTTP/1.1\r\n"
1353 "Host: www.google.com\r\n"
1354 "Connection: keep-alive\r\n"
1355 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1356 };
1357
1358 MockRead data_reads1[] = {
1359 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1360 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1361 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1362 MockRead("Content-Length: 14\r\n\r\n"),
1363 MockRead("Unauthorized\r\n"),
1364
1365 // Lastly, the server responds with the actual content.
1366 MockRead("HTTP/1.1 200 OK\r\n"),
1367 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501368 MockRead("Content-Length: 5\r\n\r\n"),
1369 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321370 };
1371
[email protected]2d0a4f92011-05-05 16:38:461372 // If there is a regression where we disconnect a Keep-Alive
1373 // connection during an auth roundtrip, we'll end up reading this.
1374 MockRead data_reads2[] = {
1375 MockRead(false, ERR_FAILED),
1376 };
1377
[email protected]31a2bfe2010-02-09 08:03:391378 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1379 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461380 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1381 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591382 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461383 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321384
[email protected]f1f3f0f82011-10-01 20:38:101385 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321386
[email protected]0b0bf032010-09-21 18:08:501387 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271388 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421389 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321390
1391 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421392 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321393
[email protected]1c773ea12009-04-28 19:58:421394 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501395 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041396 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321397
[email protected]f1f3f0f82011-10-01 20:38:101398 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321399
[email protected]13c8a092010-07-29 06:15:441400 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421401 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321402
1403 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421404 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321405
1406 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501407 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321408 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501409 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321410}
1411
1412// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1413// connection and with no response body to drain.
1414TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421415 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321416 request.method = "GET";
1417 request.url = GURL("http://www.google.com/");
1418 request.load_flags = 0;
1419
[email protected]cb9bf6ca2011-01-28 13:15:271420 SessionDependencies session_deps;
1421 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1422
[email protected]2d2697f92009-02-18 21:00:321423 MockWrite data_writes1[] = {
1424 MockWrite("GET / HTTP/1.1\r\n"
1425 "Host: www.google.com\r\n"
1426 "Connection: keep-alive\r\n\r\n"),
1427
1428 // After calling trans->RestartWithAuth(), this is the request we should
1429 // be issuing -- the final header line contains the credentials.
1430 MockWrite("GET / HTTP/1.1\r\n"
1431 "Host: www.google.com\r\n"
1432 "Connection: keep-alive\r\n"
1433 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1434 };
1435
[email protected]2d2697f92009-02-18 21:00:321436 MockRead data_reads1[] = {
1437 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1438 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311439 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321440
1441 // Lastly, the server responds with the actual content.
1442 MockRead("HTTP/1.1 200 OK\r\n"),
1443 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501444 MockRead("Content-Length: 5\r\n\r\n"),
1445 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321446 };
1447
[email protected]2d0a4f92011-05-05 16:38:461448 // An incorrect reconnect would cause this to be read.
1449 MockRead data_reads2[] = {
1450 MockRead(false, ERR_FAILED),
1451 };
1452
[email protected]31a2bfe2010-02-09 08:03:391453 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1454 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461455 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1456 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591457 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461458 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321459
[email protected]f1f3f0f82011-10-01 20:38:101460 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321461
[email protected]0b0bf032010-09-21 18:08:501462 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271463 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421464 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321465
1466 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421467 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321468
[email protected]1c773ea12009-04-28 19:58:421469 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501470 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041471 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321472
[email protected]f1f3f0f82011-10-01 20:38:101473 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321474
[email protected]13c8a092010-07-29 06:15:441475 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421476 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321477
1478 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421479 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321480
1481 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501482 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321483 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501484 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321485}
1486
1487// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1488// connection and with a large response body to drain.
1489TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421490 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321491 request.method = "GET";
1492 request.url = GURL("http://www.google.com/");
1493 request.load_flags = 0;
1494
[email protected]cb9bf6ca2011-01-28 13:15:271495 SessionDependencies session_deps;
1496 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1497
[email protected]2d2697f92009-02-18 21:00:321498 MockWrite data_writes1[] = {
1499 MockWrite("GET / HTTP/1.1\r\n"
1500 "Host: www.google.com\r\n"
1501 "Connection: keep-alive\r\n\r\n"),
1502
1503 // After calling trans->RestartWithAuth(), this is the request we should
1504 // be issuing -- the final header line contains the credentials.
1505 MockWrite("GET / HTTP/1.1\r\n"
1506 "Host: www.google.com\r\n"
1507 "Connection: keep-alive\r\n"
1508 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1509 };
1510
1511 // Respond with 5 kb of response body.
1512 std::string large_body_string("Unauthorized");
1513 large_body_string.append(5 * 1024, ' ');
1514 large_body_string.append("\r\n");
1515
1516 MockRead data_reads1[] = {
1517 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1518 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1519 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1520 // 5134 = 12 + 5 * 1024 + 2
1521 MockRead("Content-Length: 5134\r\n\r\n"),
1522 MockRead(true, large_body_string.data(), large_body_string.size()),
1523
1524 // Lastly, the server responds with the actual content.
1525 MockRead("HTTP/1.1 200 OK\r\n"),
1526 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501527 MockRead("Content-Length: 5\r\n\r\n"),
1528 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321529 };
1530
[email protected]2d0a4f92011-05-05 16:38:461531 // An incorrect reconnect would cause this to be read.
1532 MockRead data_reads2[] = {
1533 MockRead(false, ERR_FAILED),
1534 };
1535
[email protected]31a2bfe2010-02-09 08:03:391536 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1537 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461538 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1539 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591540 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461541 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321542
[email protected]f1f3f0f82011-10-01 20:38:101543 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321544
[email protected]0b0bf032010-09-21 18:08:501545 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271546 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421547 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321548
1549 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421550 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321551
[email protected]1c773ea12009-04-28 19:58:421552 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501553 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041554 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321555
[email protected]f1f3f0f82011-10-01 20:38:101556 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321557
[email protected]13c8a092010-07-29 06:15:441558 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421559 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321560
1561 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421562 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321563
1564 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501565 ASSERT_TRUE(response != NULL);
[email protected]2d2697f92009-02-18 21:00:321566 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501567 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321568}
1569
1570// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311571// connection, but the server gets impatient and closes the connection.
1572TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311573 HttpRequestInfo request;
1574 request.method = "GET";
1575 request.url = GURL("http://www.google.com/");
1576 request.load_flags = 0;
1577
[email protected]cb9bf6ca2011-01-28 13:15:271578 SessionDependencies session_deps;
1579 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1580
[email protected]11203f012009-11-12 23:02:311581 MockWrite data_writes1[] = {
1582 MockWrite("GET / HTTP/1.1\r\n"
1583 "Host: www.google.com\r\n"
1584 "Connection: keep-alive\r\n\r\n"),
1585 // This simulates the seemingly successful write to a closed connection
1586 // if the bug is not fixed.
1587 MockWrite("GET / HTTP/1.1\r\n"
1588 "Host: www.google.com\r\n"
1589 "Connection: keep-alive\r\n"
1590 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1591 };
1592
1593 MockRead data_reads1[] = {
1594 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1595 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1596 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1597 MockRead("Content-Length: 14\r\n\r\n"),
1598 // Tell MockTCPClientSocket to simulate the server closing the connection.
1599 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1600 MockRead("Unauthorized\r\n"),
1601 MockRead(false, OK), // The server closes the connection.
1602 };
1603
1604 // After calling trans->RestartWithAuth(), this is the request we should
1605 // be issuing -- the final header line contains the credentials.
1606 MockWrite data_writes2[] = {
1607 MockWrite("GET / HTTP/1.1\r\n"
1608 "Host: www.google.com\r\n"
1609 "Connection: keep-alive\r\n"
1610 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1611 };
1612
1613 // Lastly, the server responds with the actual content.
1614 MockRead data_reads2[] = {
1615 MockRead("HTTP/1.1 200 OK\r\n"),
1616 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501617 MockRead("Content-Length: 5\r\n\r\n"),
1618 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311619 };
1620
[email protected]31a2bfe2010-02-09 08:03:391621 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1622 data_writes1, arraysize(data_writes1));
1623 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1624 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311625 session_deps.socket_factory.AddSocketDataProvider(&data1);
1626 session_deps.socket_factory.AddSocketDataProvider(&data2);
1627
[email protected]f1f3f0f82011-10-01 20:38:101628 TestOldCompletionCallback callback1;
[email protected]11203f012009-11-12 23:02:311629
[email protected]0b0bf032010-09-21 18:08:501630 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271631 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311632 EXPECT_EQ(ERR_IO_PENDING, rv);
1633
1634 rv = callback1.WaitForResult();
1635 EXPECT_EQ(OK, rv);
1636
1637 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501638 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041639 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]11203f012009-11-12 23:02:311640
[email protected]f1f3f0f82011-10-01 20:38:101641 TestOldCompletionCallback callback2;
[email protected]11203f012009-11-12 23:02:311642
[email protected]13c8a092010-07-29 06:15:441643 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311644 EXPECT_EQ(ERR_IO_PENDING, rv);
1645
1646 rv = callback2.WaitForResult();
1647 EXPECT_EQ(OK, rv);
1648
1649 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501650 ASSERT_TRUE(response != NULL);
[email protected]11203f012009-11-12 23:02:311651 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501652 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311653}
1654
[email protected]394816e92010-08-03 07:38:591655// Test the request-challenge-retry sequence for basic auth, over a connection
1656// that requires a restart when setting up an SSL tunnel.
1657TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591658 HttpRequestInfo request;
1659 request.method = "GET";
1660 request.url = GURL("https://www.google.com/");
1661 // when the no authentication data flag is set.
1662 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1663
[email protected]cb9bf6ca2011-01-28 13:15:271664 // Configure against proxy server "myproxy:70".
1665 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1666 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1667 session_deps.net_log = log.bound().net_log();
1668 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1669
[email protected]394816e92010-08-03 07:38:591670 // Since we have proxy, should try to establish tunnel.
1671 MockWrite data_writes1[] = {
1672 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1673 "Host: www.google.com\r\n"
1674 "Proxy-Connection: keep-alive\r\n\r\n"),
1675
1676 // After calling trans->RestartWithAuth(), this is the request we should
1677 // be issuing -- the final header line contains the credentials.
1678 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1679 "Host: www.google.com\r\n"
1680 "Proxy-Connection: keep-alive\r\n"
1681 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1682
1683 MockWrite("GET / HTTP/1.1\r\n"
1684 "Host: www.google.com\r\n"
1685 "Connection: keep-alive\r\n\r\n"),
1686 };
1687
1688 // The proxy responds to the connect with a 407, using a persistent
1689 // connection.
1690 MockRead data_reads1[] = {
1691 // No credentials.
1692 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1693 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1694 MockRead("Proxy-Connection: close\r\n\r\n"),
1695
1696 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1697
1698 MockRead("HTTP/1.1 200 OK\r\n"),
1699 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501700 MockRead("Content-Length: 5\r\n\r\n"),
1701 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591702 };
1703
1704 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1705 data_writes1, arraysize(data_writes1));
1706 session_deps.socket_factory.AddSocketDataProvider(&data1);
1707 SSLSocketDataProvider ssl(true, OK);
1708 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1709
[email protected]f1f3f0f82011-10-01 20:38:101710 TestOldCompletionCallback callback1;
[email protected]394816e92010-08-03 07:38:591711
[email protected]0b0bf032010-09-21 18:08:501712 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1713
[email protected]394816e92010-08-03 07:38:591714 int rv = trans->Start(&request, &callback1, log.bound());
1715 EXPECT_EQ(ERR_IO_PENDING, rv);
1716
1717 rv = callback1.WaitForResult();
1718 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401719 net::CapturingNetLog::EntryList entries;
1720 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591721 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401722 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591723 NetLog::PHASE_NONE);
1724 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401725 entries, pos,
[email protected]394816e92010-08-03 07:38:591726 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1727 NetLog::PHASE_NONE);
1728
1729 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501730 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041731 ASSERT_FALSE(response->headers == NULL);
[email protected]394816e92010-08-03 07:38:591732 EXPECT_EQ(407, response->headers->response_code());
1733 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041734 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]394816e92010-08-03 07:38:591735
[email protected]f1f3f0f82011-10-01 20:38:101736 TestOldCompletionCallback callback2;
[email protected]394816e92010-08-03 07:38:591737
1738 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1739 EXPECT_EQ(ERR_IO_PENDING, rv);
1740
1741 rv = callback2.WaitForResult();
1742 EXPECT_EQ(OK, rv);
1743
1744 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501745 ASSERT_TRUE(response != NULL);
[email protected]394816e92010-08-03 07:38:591746
1747 EXPECT_TRUE(response->headers->IsKeepAlive());
1748 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501749 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591750 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1751
1752 // The password prompt info should not be set.
1753 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501754
1755 trans.reset();
[email protected]102e27c2011-02-23 01:01:311756 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591757}
1758
[email protected]11203f012009-11-12 23:02:311759// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321760// proxy connection, when setting up an SSL tunnel.
1761TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271762 HttpRequestInfo request;
1763 request.method = "GET";
1764 request.url = GURL("https://www.google.com/");
1765 // Ensure that proxy authentication is attempted even
1766 // when the no authentication data flag is set.
1767 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1768
[email protected]2d2697f92009-02-18 21:00:321769 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001770 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541771 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1772 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591773 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321774
[email protected]5695b8c2009-09-30 21:36:431775 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321776
[email protected]2d2697f92009-02-18 21:00:321777 // Since we have proxy, should try to establish tunnel.
1778 MockWrite data_writes1[] = {
1779 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451780 "Host: www.google.com\r\n"
1781 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321782
1783 // After calling trans->RestartWithAuth(), this is the request we should
1784 // be issuing -- the final header line contains the credentials.
1785 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1786 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451787 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321788 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1789 };
1790
1791 // The proxy responds to the connect with a 407, using a persistent
1792 // connection.
1793 MockRead data_reads1[] = {
1794 // No credentials.
1795 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1796 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1797 MockRead("Content-Length: 10\r\n\r\n"),
1798 MockRead("0123456789"),
1799
1800 // Wrong credentials (wrong password).
1801 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1802 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1803 MockRead("Content-Length: 10\r\n\r\n"),
1804 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421805 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321806 };
1807
[email protected]31a2bfe2010-02-09 08:03:391808 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1809 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591810 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321811
[email protected]f1f3f0f82011-10-01 20:38:101812 TestOldCompletionCallback callback1;
[email protected]2d2697f92009-02-18 21:00:321813
[email protected]dbb83db2010-05-11 18:13:391814 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421815 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321816
1817 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421818 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401819 net::CapturingNetLog::EntryList entries;
1820 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391821 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401822 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391823 NetLog::PHASE_NONE);
1824 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401825 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391826 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1827 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321828
[email protected]1c773ea12009-04-28 19:58:421829 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501830 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041831 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321832 EXPECT_TRUE(response->headers->IsKeepAlive());
1833 EXPECT_EQ(407, response->headers->response_code());
1834 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421835 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041836 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2d2697f92009-02-18 21:00:321837
[email protected]f1f3f0f82011-10-01 20:38:101838 TestOldCompletionCallback callback2;
[email protected]2d2697f92009-02-18 21:00:321839
1840 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441841 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421842 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321843
1844 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421845 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321846
1847 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501848 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:041849 ASSERT_FALSE(response->headers == NULL);
[email protected]2d2697f92009-02-18 21:00:321850 EXPECT_TRUE(response->headers->IsKeepAlive());
1851 EXPECT_EQ(407, response->headers->response_code());
1852 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421853 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:041854 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]e772db3f2010-07-12 18:11:131855
[email protected]e60e47a2010-07-14 03:37:181856 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1857 // out of scope.
[email protected]102e27c2011-02-23 01:01:311858 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321859}
1860
[email protected]a8e9b162009-03-12 00:06:441861// Test that we don't read the response body when we fail to establish a tunnel,
1862// even if the user cancels the proxy's auth attempt.
1863TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271864 HttpRequestInfo request;
1865 request.method = "GET";
1866 request.url = GURL("https://www.google.com/");
1867 request.load_flags = 0;
1868
[email protected]a8e9b162009-03-12 00:06:441869 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001870 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441871
[email protected]e44de5d2009-06-05 20:12:451872 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441873
[email protected]5695b8c2009-09-30 21:36:431874 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441875
[email protected]a8e9b162009-03-12 00:06:441876 // Since we have proxy, should try to establish tunnel.
1877 MockWrite data_writes[] = {
1878 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451879 "Host: www.google.com\r\n"
1880 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441881 };
1882
1883 // The proxy responds to the connect with a 407.
1884 MockRead data_reads[] = {
1885 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1886 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1887 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421888 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441889 };
1890
[email protected]31a2bfe2010-02-09 08:03:391891 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1892 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591893 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441894
[email protected]f1f3f0f82011-10-01 20:38:101895 TestOldCompletionCallback callback;
[email protected]a8e9b162009-03-12 00:06:441896
[email protected]5a1d7ca2010-04-28 20:12:271897 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421898 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441899
1900 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421901 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441902
[email protected]1c773ea12009-04-28 19:58:421903 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:501904 ASSERT_TRUE(response != NULL);
[email protected]a8e9b162009-03-12 00:06:441905
1906 EXPECT_TRUE(response->headers->IsKeepAlive());
1907 EXPECT_EQ(407, response->headers->response_code());
1908 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421909 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441910
1911 std::string response_data;
1912 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421913 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181914
1915 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311916 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441917}
1918
[email protected]8fdbcd22010-05-05 02:54:521919// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1920// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1921TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521922 HttpRequestInfo request;
1923 request.method = "GET";
1924 request.url = GURL("http://www.google.com/");
1925 request.load_flags = 0;
1926
[email protected]cb9bf6ca2011-01-28 13:15:271927 // We are using a DIRECT connection (i.e. no proxy) for this session.
1928 SessionDependencies session_deps;
1929 scoped_ptr<HttpTransaction> trans(
1930 new HttpNetworkTransaction(CreateSession(&session_deps)));
1931
[email protected]8fdbcd22010-05-05 02:54:521932 MockWrite data_writes1[] = {
1933 MockWrite("GET / HTTP/1.1\r\n"
1934 "Host: www.google.com\r\n"
1935 "Connection: keep-alive\r\n\r\n"),
1936 };
1937
1938 MockRead data_reads1[] = {
1939 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1940 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1941 // Large content-length -- won't matter, as connection will be reset.
1942 MockRead("Content-Length: 10000\r\n\r\n"),
1943 MockRead(false, ERR_FAILED),
1944 };
1945
1946 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1947 data_writes1, arraysize(data_writes1));
1948 session_deps.socket_factory.AddSocketDataProvider(&data1);
1949
[email protected]f1f3f0f82011-10-01 20:38:101950 TestOldCompletionCallback callback;
[email protected]8fdbcd22010-05-05 02:54:521951
1952 int rv = trans->Start(&request, &callback, BoundNetLog());
1953 EXPECT_EQ(ERR_IO_PENDING, rv);
1954
1955 rv = callback.WaitForResult();
1956 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1957}
1958
[email protected]7a67a8152010-11-05 18:31:101959// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1960// through a non-authenticating proxy. The request should fail with
1961// ERR_UNEXPECTED_PROXY_AUTH.
1962// Note that it is impossible to detect if an HTTP server returns a 407 through
1963// a non-authenticating proxy - there is nothing to indicate whether the
1964// response came from the proxy or the server, so it is treated as if the proxy
1965// issued the challenge.
1966TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271967 HttpRequestInfo request;
1968 request.method = "GET";
1969 request.url = GURL("https://www.google.com/");
1970
[email protected]7a67a8152010-11-05 18:31:101971 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1972 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1973 session_deps.net_log = log.bound().net_log();
1974 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1975
[email protected]7a67a8152010-11-05 18:31:101976 // Since we have proxy, should try to establish tunnel.
1977 MockWrite data_writes1[] = {
1978 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1979 "Host: www.google.com\r\n"
1980 "Proxy-Connection: keep-alive\r\n\r\n"),
1981
1982 MockWrite("GET / HTTP/1.1\r\n"
1983 "Host: www.google.com\r\n"
1984 "Connection: keep-alive\r\n\r\n"),
1985 };
1986
1987 MockRead data_reads1[] = {
1988 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1989
1990 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1991 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1992 MockRead("\r\n"),
1993 MockRead(false, OK),
1994 };
1995
1996 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1997 data_writes1, arraysize(data_writes1));
1998 session_deps.socket_factory.AddSocketDataProvider(&data1);
1999 SSLSocketDataProvider ssl(true, OK);
2000 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2001
[email protected]f1f3f0f82011-10-01 20:38:102002 TestOldCompletionCallback callback1;
[email protected]7a67a8152010-11-05 18:31:102003
2004 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2005
2006 int rv = trans->Start(&request, &callback1, log.bound());
2007 EXPECT_EQ(ERR_IO_PENDING, rv);
2008
2009 rv = callback1.WaitForResult();
2010 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:402011 net::CapturingNetLog::EntryList entries;
2012 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:102013 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402014 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:102015 NetLog::PHASE_NONE);
2016 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:402017 entries, pos,
[email protected]7a67a8152010-11-05 18:31:102018 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
2019 NetLog::PHASE_NONE);
2020}
[email protected]2df19bb2010-08-25 20:13:462021
2022// Test a simple get through an HTTPS Proxy.
2023TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272024 HttpRequestInfo request;
2025 request.method = "GET";
2026 request.url = GURL("http://www.google.com/");
2027
[email protected]2df19bb2010-08-25 20:13:462028 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112029 SessionDependencies session_deps(ProxyService::CreateFixed(
2030 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:462031 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2032 session_deps.net_log = log.bound().net_log();
2033 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2034
[email protected]2df19bb2010-08-25 20:13:462035 // Since we have proxy, should use full url
2036 MockWrite data_writes1[] = {
2037 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2038 "Host: www.google.com\r\n"
2039 "Proxy-Connection: keep-alive\r\n\r\n"),
2040 };
2041
2042 MockRead data_reads1[] = {
2043 MockRead("HTTP/1.1 200 OK\r\n"),
2044 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2045 MockRead("Content-Length: 100\r\n\r\n"),
2046 MockRead(false, OK),
2047 };
2048
2049 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2050 data_writes1, arraysize(data_writes1));
2051 session_deps.socket_factory.AddSocketDataProvider(&data1);
2052 SSLSocketDataProvider ssl(true, OK);
2053 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2054
[email protected]f1f3f0f82011-10-01 20:38:102055 TestOldCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462056
[email protected]0b0bf032010-09-21 18:08:502057 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2058
[email protected]2df19bb2010-08-25 20:13:462059 int rv = trans->Start(&request, &callback1, log.bound());
2060 EXPECT_EQ(ERR_IO_PENDING, rv);
2061
2062 rv = callback1.WaitForResult();
2063 EXPECT_EQ(OK, rv);
2064
2065 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502066 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462067
2068 EXPECT_TRUE(response->headers->IsKeepAlive());
2069 EXPECT_EQ(200, response->headers->response_code());
2070 EXPECT_EQ(100, response->headers->GetContentLength());
2071 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2072
2073 // The password prompt info should not be set.
2074 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2075}
2076
[email protected]7642b5ae2010-09-01 20:55:172077// Test a SPDY get through an HTTPS Proxy.
2078TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:272079 HttpRequestInfo request;
2080 request.method = "GET";
2081 request.url = GURL("http://www.google.com/");
2082 request.load_flags = 0;
2083
[email protected]7642b5ae2010-09-01 20:55:172084 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112085 SessionDependencies session_deps(ProxyService::CreateFixed(
2086 "https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:172087 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2088 session_deps.net_log = log.bound().net_log();
2089 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2090
[email protected]7642b5ae2010-09-01 20:55:172091 // fetch http://www.google.com/ via SPDY
2092 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
2093 false));
2094 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
2095
2096 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2097 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2098 MockRead spdy_reads[] = {
2099 CreateMockRead(*resp),
2100 CreateMockRead(*data),
2101 MockRead(true, 0, 0),
2102 };
2103
2104 scoped_refptr<DelayedSocketData> spdy_data(
2105 new DelayedSocketData(
2106 1, // wait for one write to finish before reading.
2107 spdy_reads, arraysize(spdy_reads),
2108 spdy_writes, arraysize(spdy_writes)));
2109 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2110
2111 SSLSocketDataProvider ssl(true, OK);
2112 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2113 ssl.next_proto = "spdy/2";
2114 ssl.was_npn_negotiated = true;
2115 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2116
[email protected]f1f3f0f82011-10-01 20:38:102117 TestOldCompletionCallback callback1;
[email protected]7642b5ae2010-09-01 20:55:172118
[email protected]0b0bf032010-09-21 18:08:502119 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2120
[email protected]7642b5ae2010-09-01 20:55:172121 int rv = trans->Start(&request, &callback1, log.bound());
2122 EXPECT_EQ(ERR_IO_PENDING, rv);
2123
2124 rv = callback1.WaitForResult();
2125 EXPECT_EQ(OK, rv);
2126
2127 const HttpResponseInfo* response = trans->GetResponseInfo();
2128 ASSERT_TRUE(response != NULL);
2129 ASSERT_TRUE(response->headers != NULL);
2130 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2131
2132 std::string response_data;
2133 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2134 EXPECT_EQ(net::kUploadData, response_data);
2135}
2136
[email protected]dc7bd1c52010-11-12 00:01:132137// Test a SPDY get through an HTTPS Proxy.
2138TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272139 HttpRequestInfo request;
2140 request.method = "GET";
2141 request.url = GURL("http://www.google.com/");
2142 request.load_flags = 0;
2143
[email protected]79cb5c12011-09-12 13:12:042144 // Configure against https proxy server "myproxy:70".
[email protected]dc7bd1c52010-11-12 00:01:132145 SessionDependencies session_deps(
[email protected]79cb5c12011-09-12 13:12:042146 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]dc7bd1c52010-11-12 00:01:132147 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2148 session_deps.net_log = log.bound().net_log();
2149 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2150
[email protected]dc7bd1c52010-11-12 00:01:132151 // The first request will be a bare GET, the second request will be a
2152 // GET with a Proxy-Authorization header.
2153 scoped_ptr<spdy::SpdyFrame> req_get(
2154 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2155 const char* const kExtraAuthorizationHeaders[] = {
2156 "proxy-authorization",
2157 "Basic Zm9vOmJhcg==",
2158 };
2159 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2160 ConstructSpdyGet(
2161 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2162 false, 3, LOWEST, false));
2163 MockWrite spdy_writes[] = {
2164 CreateMockWrite(*req_get, 1),
2165 CreateMockWrite(*req_get_authorization, 4),
2166 };
2167
2168 // The first response is a 407 proxy authentication challenge, and the second
2169 // response will be a 200 response since the second request includes a valid
2170 // Authorization header.
2171 const char* const kExtraAuthenticationHeaders[] = {
2172 "Proxy-Authenticate",
2173 "Basic realm=\"MyRealm1\""
2174 };
2175 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2176 ConstructSpdySynReplyError(
2177 "407 Proxy Authentication Required",
2178 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2179 1));
2180 scoped_ptr<spdy::SpdyFrame> body_authentication(
2181 ConstructSpdyBodyFrame(1, true));
2182 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2183 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2184 MockRead spdy_reads[] = {
2185 CreateMockRead(*resp_authentication, 2),
2186 CreateMockRead(*body_authentication, 3),
2187 CreateMockRead(*resp_data, 5),
2188 CreateMockRead(*body_data, 6),
2189 MockRead(true, 0, 7),
2190 };
2191
2192 scoped_refptr<OrderedSocketData> data(
2193 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2194 spdy_writes, arraysize(spdy_writes)));
2195 session_deps.socket_factory.AddSocketDataProvider(data);
2196
2197 SSLSocketDataProvider ssl(true, OK);
2198 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2199 ssl.next_proto = "spdy/2";
2200 ssl.was_npn_negotiated = true;
2201 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2202
[email protected]f1f3f0f82011-10-01 20:38:102203 TestOldCompletionCallback callback1;
[email protected]dc7bd1c52010-11-12 00:01:132204
2205 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2206
2207 int rv = trans->Start(&request, &callback1, log.bound());
2208 EXPECT_EQ(ERR_IO_PENDING, rv);
2209
2210 rv = callback1.WaitForResult();
2211 EXPECT_EQ(OK, rv);
2212
2213 const HttpResponseInfo* const response = trans->GetResponseInfo();
2214
2215 ASSERT_TRUE(response != NULL);
2216 ASSERT_TRUE(response->headers != NULL);
2217 EXPECT_EQ(407, response->headers->response_code());
2218 EXPECT_TRUE(response->was_fetched_via_spdy);
[email protected]79cb5c12011-09-12 13:12:042219 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]dc7bd1c52010-11-12 00:01:132220
[email protected]f1f3f0f82011-10-01 20:38:102221 TestOldCompletionCallback callback2;
[email protected]dc7bd1c52010-11-12 00:01:132222
2223 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2224 EXPECT_EQ(ERR_IO_PENDING, rv);
2225
2226 rv = callback2.WaitForResult();
2227 EXPECT_EQ(OK, rv);
2228
2229 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2230
2231 ASSERT_TRUE(response_restart != NULL);
2232 ASSERT_TRUE(response_restart->headers != NULL);
2233 EXPECT_EQ(200, response_restart->headers->response_code());
2234 // The password prompt info should not be set.
2235 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2236}
2237
[email protected]d9da5fe2010-10-13 22:37:162238// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2239TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272240 HttpRequestInfo request;
2241 request.method = "GET";
2242 request.url = GURL("https://www.google.com/");
2243 request.load_flags = 0;
2244
[email protected]d9da5fe2010-10-13 22:37:162245 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112246 SessionDependencies session_deps(ProxyService::CreateFixed(
2247 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162248 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2249 session_deps.net_log = log.bound().net_log();
2250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2251
2252 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2253
[email protected]d9da5fe2010-10-13 22:37:162254 // CONNECT to www.google.com:443 via SPDY
2255 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2256 // fetch https://www.google.com/ via HTTP
2257
2258 const char get[] = "GET / HTTP/1.1\r\n"
2259 "Host: www.google.com\r\n"
2260 "Connection: keep-alive\r\n\r\n";
2261 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2262 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2263 MockWrite spdy_writes[] = {
2264 CreateMockWrite(*connect, 1),
2265 CreateMockWrite(*wrapped_get, 3)
2266 };
2267
2268 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2269 const char resp[] = "HTTP/1.1 200 OK\r\n"
2270 "Content-Length: 10\r\n\r\n";
2271
2272 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2273 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2274 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2275 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2276 MockRead spdy_reads[] = {
2277 CreateMockRead(*conn_resp, 2, true),
2278 CreateMockRead(*wrapped_get_resp, 4, true),
2279 CreateMockRead(*wrapped_body, 5, true),
2280 CreateMockRead(*wrapped_body, 6, true),
2281 MockRead(true, 0, 7),
2282 };
2283
2284 scoped_refptr<OrderedSocketData> spdy_data(
2285 new OrderedSocketData(
2286 spdy_reads, arraysize(spdy_reads),
2287 spdy_writes, arraysize(spdy_writes)));
2288 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2289
2290 SSLSocketDataProvider ssl(true, OK);
2291 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2292 ssl.next_proto = "spdy/2";
2293 ssl.was_npn_negotiated = true;
2294 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2295 SSLSocketDataProvider ssl2(true, OK);
2296 ssl2.was_npn_negotiated = false;
2297 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2298
[email protected]f1f3f0f82011-10-01 20:38:102299 TestOldCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162300
2301 int rv = trans->Start(&request, &callback1, log.bound());
2302 EXPECT_EQ(ERR_IO_PENDING, rv);
2303
2304 rv = callback1.WaitForResult();
2305 EXPECT_EQ(OK, rv);
2306
2307 const HttpResponseInfo* response = trans->GetResponseInfo();
2308 ASSERT_TRUE(response != NULL);
2309 ASSERT_TRUE(response->headers != NULL);
2310 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2311
2312 std::string response_data;
2313 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2314 EXPECT_EQ("1234567890", response_data);
2315}
2316
2317// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2318TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272319 HttpRequestInfo request;
2320 request.method = "GET";
2321 request.url = GURL("https://www.google.com/");
2322 request.load_flags = 0;
2323
[email protected]d9da5fe2010-10-13 22:37:162324 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112325 SessionDependencies session_deps(ProxyService::CreateFixed(
2326 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162327 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2328 session_deps.net_log = log.bound().net_log();
2329 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2330
2331 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2332
[email protected]d9da5fe2010-10-13 22:37:162333 // CONNECT to www.google.com:443 via SPDY
2334 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2335 // fetch https://www.google.com/ via SPDY
2336 const char* const kMyUrl = "https://www.google.com/";
2337 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2338 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2339 MockWrite spdy_writes[] = {
2340 CreateMockWrite(*connect, 1),
2341 CreateMockWrite(*wrapped_get, 3)
2342 };
2343
2344 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2345 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2346 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2347 ConstructWrappedSpdyFrame(get_resp, 1));
2348 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2349 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2350 MockRead spdy_reads[] = {
2351 CreateMockRead(*conn_resp, 2, true),
2352 CreateMockRead(*wrapped_get_resp, 4, true),
2353 CreateMockRead(*wrapped_body, 5, true),
2354 MockRead(true, 0, 1),
2355 };
2356
2357 scoped_refptr<OrderedSocketData> spdy_data(
2358 new OrderedSocketData(
2359 spdy_reads, arraysize(spdy_reads),
2360 spdy_writes, arraysize(spdy_writes)));
2361 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2362
2363 SSLSocketDataProvider ssl(true, OK);
2364 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2365 ssl.next_proto = "spdy/2";
2366 ssl.was_npn_negotiated = true;
2367 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2368 SSLSocketDataProvider ssl2(true, OK);
2369 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2370 ssl2.next_proto = "spdy/2";
2371 ssl2.was_npn_negotiated = true;
2372 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2373
[email protected]f1f3f0f82011-10-01 20:38:102374 TestOldCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162375
2376 int rv = trans->Start(&request, &callback1, log.bound());
2377 EXPECT_EQ(ERR_IO_PENDING, rv);
2378
2379 rv = callback1.WaitForResult();
2380 EXPECT_EQ(OK, rv);
2381
2382 const HttpResponseInfo* response = trans->GetResponseInfo();
2383 ASSERT_TRUE(response != NULL);
2384 ASSERT_TRUE(response->headers != NULL);
2385 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2386
2387 std::string response_data;
2388 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2389 EXPECT_EQ(net::kUploadData, response_data);
2390}
2391
2392// Test a SPDY CONNECT failure through an HTTPS Proxy.
2393TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272394 HttpRequestInfo request;
2395 request.method = "GET";
2396 request.url = GURL("https://www.google.com/");
2397 request.load_flags = 0;
2398
[email protected]d9da5fe2010-10-13 22:37:162399 // Configure against https proxy server "proxy:70".
[email protected]3912662a32011-10-04 00:51:112400 SessionDependencies session_deps(ProxyService::CreateFixed(
2401 "https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162402 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2403 session_deps.net_log = log.bound().net_log();
2404 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2405
2406 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2407
[email protected]d9da5fe2010-10-13 22:37:162408 // CONNECT to www.google.com:443 via SPDY
2409 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2410 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2411
2412 MockWrite spdy_writes[] = {
2413 CreateMockWrite(*connect, 1),
2414 CreateMockWrite(*get, 3),
2415 };
2416
2417 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2418 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2419 MockRead spdy_reads[] = {
2420 CreateMockRead(*resp, 2, true),
2421 MockRead(true, 0, 4),
2422 };
2423
2424 scoped_refptr<OrderedSocketData> spdy_data(
2425 new OrderedSocketData(
2426 spdy_reads, arraysize(spdy_reads),
2427 spdy_writes, arraysize(spdy_writes)));
2428 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2429
2430 SSLSocketDataProvider ssl(true, OK);
2431 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2432 ssl.next_proto = "spdy/2";
2433 ssl.was_npn_negotiated = true;
2434 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2435 SSLSocketDataProvider ssl2(true, OK);
2436 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2437 ssl2.next_proto = "spdy/2";
2438 ssl2.was_npn_negotiated = true;
2439 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2440
[email protected]f1f3f0f82011-10-01 20:38:102441 TestOldCompletionCallback callback1;
[email protected]d9da5fe2010-10-13 22:37:162442
2443 int rv = trans->Start(&request, &callback1, log.bound());
2444 EXPECT_EQ(ERR_IO_PENDING, rv);
2445
2446 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292447 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162448
2449 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502450 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:292451 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162452}
2453
[email protected]2df19bb2010-08-25 20:13:462454// Test the challenge-response-retry sequence through an HTTPS Proxy
2455TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462456 HttpRequestInfo request;
2457 request.method = "GET";
2458 request.url = GURL("http://www.google.com/");
2459 // when the no authentication data flag is set.
2460 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2461
[email protected]79cb5c12011-09-12 13:12:042462 // Configure against https proxy server "myproxy:70".
2463 SessionDependencies session_deps(
2464 ProxyService::CreateFixed("https://myproxy:70"));
[email protected]cb9bf6ca2011-01-28 13:15:272465 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2466 session_deps.net_log = log.bound().net_log();
2467 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2468
[email protected]2df19bb2010-08-25 20:13:462469 // Since we have proxy, should use full url
2470 MockWrite data_writes1[] = {
2471 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2472 "Host: www.google.com\r\n"
2473 "Proxy-Connection: keep-alive\r\n\r\n"),
2474
2475 // After calling trans->RestartWithAuth(), this is the request we should
2476 // be issuing -- the final header line contains the credentials.
2477 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2478 "Host: www.google.com\r\n"
2479 "Proxy-Connection: keep-alive\r\n"
2480 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2481 };
2482
2483 // The proxy responds to the GET with a 407, using a persistent
2484 // connection.
2485 MockRead data_reads1[] = {
2486 // No credentials.
2487 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2488 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2489 MockRead("Proxy-Connection: keep-alive\r\n"),
2490 MockRead("Content-Length: 0\r\n\r\n"),
2491
2492 MockRead("HTTP/1.1 200 OK\r\n"),
2493 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2494 MockRead("Content-Length: 100\r\n\r\n"),
2495 MockRead(false, OK),
2496 };
2497
2498 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2499 data_writes1, arraysize(data_writes1));
2500 session_deps.socket_factory.AddSocketDataProvider(&data1);
2501 SSLSocketDataProvider ssl(true, OK);
2502 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2503
[email protected]f1f3f0f82011-10-01 20:38:102504 TestOldCompletionCallback callback1;
[email protected]2df19bb2010-08-25 20:13:462505
[email protected]0b0bf032010-09-21 18:08:502506 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2507
[email protected]2df19bb2010-08-25 20:13:462508 int rv = trans->Start(&request, &callback1, log.bound());
2509 EXPECT_EQ(ERR_IO_PENDING, rv);
2510
2511 rv = callback1.WaitForResult();
2512 EXPECT_EQ(OK, rv);
2513
2514 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502515 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042516 ASSERT_FALSE(response->headers == NULL);
[email protected]2df19bb2010-08-25 20:13:462517 EXPECT_EQ(407, response->headers->response_code());
2518 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]79cb5c12011-09-12 13:12:042519 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]2df19bb2010-08-25 20:13:462520
[email protected]f1f3f0f82011-10-01 20:38:102521 TestOldCompletionCallback callback2;
[email protected]2df19bb2010-08-25 20:13:462522
2523 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2524 EXPECT_EQ(ERR_IO_PENDING, rv);
2525
2526 rv = callback2.WaitForResult();
2527 EXPECT_EQ(OK, rv);
2528
2529 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502530 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:462531
2532 EXPECT_TRUE(response->headers->IsKeepAlive());
2533 EXPECT_EQ(200, response->headers->response_code());
2534 EXPECT_EQ(100, response->headers->GetContentLength());
2535 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2536
2537 // The password prompt info should not be set.
2538 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2539}
2540
[email protected]ff007e162009-05-23 09:13:152541void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082542 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422543 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082544 request.method = "GET";
2545 request.url = GURL("https://www.google.com/");
2546 request.load_flags = 0;
2547
[email protected]cb9bf6ca2011-01-28 13:15:272548 // Configure against proxy server "myproxy:70".
2549 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2550
2551 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2552
[email protected]c744cf22009-02-27 07:28:082553 // Since we have proxy, should try to establish tunnel.
2554 MockWrite data_writes[] = {
2555 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452556 "Host: www.google.com\r\n"
2557 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082558 };
2559
2560 MockRead data_reads[] = {
2561 status,
2562 MockRead("Content-Length: 10\r\n\r\n"),
2563 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422564 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082565 };
2566
[email protected]31a2bfe2010-02-09 08:03:392567 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2568 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592569 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082570
[email protected]f1f3f0f82011-10-01 20:38:102571 TestOldCompletionCallback callback;
[email protected]c744cf22009-02-27 07:28:082572
[email protected]0b0bf032010-09-21 18:08:502573 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2574
[email protected]5a1d7ca2010-04-28 20:12:272575 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422576 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082577
2578 rv = callback.WaitForResult();
2579 EXPECT_EQ(expected_status, rv);
2580}
2581
[email protected]ff007e162009-05-23 09:13:152582void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082583 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422584 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082585}
2586
2587TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2588 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2589}
2590
2591TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2592 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2593}
2594
2595TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2596 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2597}
2598
2599TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2600 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2601}
2602
2603TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2604 ConnectStatusHelper(
2605 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2606}
2607
2608TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2609 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2610}
2611
2612TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2613 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2614}
2615
2616TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2617 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2618}
2619
2620TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2621 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2622}
2623
2624TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2625 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2626}
2627
2628TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2629 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2630}
2631
2632TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2633 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2634}
2635
2636TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2637 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2638}
2639
2640TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2641 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2642}
2643
2644TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2645 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2646}
2647
2648TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2649 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2650}
2651
2652TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2653 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2654}
2655
2656TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2657 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2658}
2659
2660TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2661 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2662}
2663
2664TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2665 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2666}
2667
2668TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2669 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2670}
2671
2672TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2673 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2674}
2675
2676TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2677 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2678}
2679
2680TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2681 ConnectStatusHelperWithExpectedStatus(
2682 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542683 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082684}
2685
2686TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2687 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2688}
2689
2690TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2691 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2692}
2693
2694TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2695 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2696}
2697
2698TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2699 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2700}
2701
2702TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2703 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2704}
2705
2706TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2707 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2708}
2709
2710TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2711 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2712}
2713
2714TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2715 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2716}
2717
2718TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2719 ConnectStatusHelper(
2720 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2721}
2722
2723TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2724 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2725}
2726
2727TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2728 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2729}
2730
2731TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2732 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2733}
2734
2735TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2736 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2737}
2738
2739TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2740 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2741}
2742
2743TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2744 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2745}
2746
2747TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2748 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2749}
2750
[email protected]038e9a32008-10-08 22:40:162751// Test the flow when both the proxy server AND origin server require
2752// authentication. Again, this uses basic auth for both since that is
2753// the simplest to mock.
2754TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272755 HttpRequestInfo request;
2756 request.method = "GET";
2757 request.url = GURL("http://www.google.com/");
2758 request.load_flags = 0;
2759
[email protected]81cdfcd2010-10-16 00:49:002760 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012761
[email protected]038e9a32008-10-08 22:40:162762 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422763 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432764 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162765
[email protected]f9ee6b52008-11-08 06:46:232766 MockWrite data_writes1[] = {
2767 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2768 "Host: www.google.com\r\n"
2769 "Proxy-Connection: keep-alive\r\n\r\n"),
2770 };
2771
[email protected]038e9a32008-10-08 22:40:162772 MockRead data_reads1[] = {
2773 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2774 // Give a couple authenticate options (only the middle one is actually
2775 // supported).
[email protected]22927ad2009-09-21 19:56:192776 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162777 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2778 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2779 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2780 // Large content-length -- won't matter, as connection will be reset.
2781 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422782 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162783 };
2784
2785 // After calling trans->RestartWithAuth() the first time, this is the
2786 // request we should be issuing -- the final header line contains the
2787 // proxy's credentials.
2788 MockWrite data_writes2[] = {
2789 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2790 "Host: www.google.com\r\n"
2791 "Proxy-Connection: keep-alive\r\n"
2792 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2793 };
2794
2795 // Now the proxy server lets the request pass through to origin server.
2796 // The origin server responds with a 401.
2797 MockRead data_reads2[] = {
2798 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2799 // Note: We are using the same realm-name as the proxy server. This is
2800 // completely valid, as realms are unique across hosts.
2801 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2802 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2803 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422804 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162805 };
2806
2807 // After calling trans->RestartWithAuth() the second time, we should send
2808 // the credentials for both the proxy and origin server.
2809 MockWrite data_writes3[] = {
2810 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2811 "Host: www.google.com\r\n"
2812 "Proxy-Connection: keep-alive\r\n"
2813 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2814 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2815 };
2816
2817 // Lastly we get the desired content.
2818 MockRead data_reads3[] = {
2819 MockRead("HTTP/1.0 200 OK\r\n"),
2820 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2821 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422822 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162823 };
2824
[email protected]31a2bfe2010-02-09 08:03:392825 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2826 data_writes1, arraysize(data_writes1));
2827 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2828 data_writes2, arraysize(data_writes2));
2829 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2830 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592831 session_deps.socket_factory.AddSocketDataProvider(&data1);
2832 session_deps.socket_factory.AddSocketDataProvider(&data2);
2833 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162834
[email protected]f1f3f0f82011-10-01 20:38:102835 TestOldCompletionCallback callback1;
[email protected]038e9a32008-10-08 22:40:162836
[email protected]5a1d7ca2010-04-28 20:12:272837 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422838 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162839
2840 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422841 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162842
[email protected]1c773ea12009-04-28 19:58:422843 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502844 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042845 EXPECT_TRUE(CheckBasicProxyAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162846
[email protected]f1f3f0f82011-10-01 20:38:102847 TestOldCompletionCallback callback2;
[email protected]038e9a32008-10-08 22:40:162848
[email protected]13c8a092010-07-29 06:15:442849 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422850 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162851
2852 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422853 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162854
2855 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:502856 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:042857 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]038e9a32008-10-08 22:40:162858
[email protected]f1f3f0f82011-10-01 20:38:102859 TestOldCompletionCallback callback3;
[email protected]038e9a32008-10-08 22:40:162860
[email protected]13c8a092010-07-29 06:15:442861 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422862 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162863
2864 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422865 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162866
2867 response = trans->GetResponseInfo();
2868 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2869 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162870}
[email protected]4ddaf2502008-10-23 18:26:192871
[email protected]ea9dc9a2009-09-05 00:43:322872// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2873// can't hook into its internals to cause it to generate predictable NTLM
2874// authorization headers.
2875#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292876// The NTLM authentication unit tests were generated by capturing the HTTP
2877// requests and responses using Fiddler 2 and inspecting the generated random
2878// bytes in the debugger.
2879
2880// Enter the correct password and authenticate successfully.
2881TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422882 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242883 request.method = "GET";
2884 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2885 request.load_flags = 0;
2886
[email protected]cb9bf6ca2011-01-28 13:15:272887 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2888 MockGetHostName);
2889 SessionDependencies session_deps;
2890 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2891
[email protected]3f918782009-02-28 01:29:242892 MockWrite data_writes1[] = {
2893 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2894 "Host: 172.22.68.17\r\n"
2895 "Connection: keep-alive\r\n\r\n"),
2896 };
2897
2898 MockRead data_reads1[] = {
2899 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042900 // Negotiate and NTLM are often requested together. However, we only want
2901 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2902 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242903 MockRead("WWW-Authenticate: NTLM\r\n"),
2904 MockRead("Connection: close\r\n"),
2905 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362906 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242907 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422908 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242909 };
2910
2911 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222912 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242913 // request we should be issuing -- the final header line contains a Type
2914 // 1 message.
2915 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2916 "Host: 172.22.68.17\r\n"
2917 "Connection: keep-alive\r\n"
2918 "Authorization: NTLM "
2919 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2920
2921 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2922 // (the credentials for the origin server). The second request continues
2923 // on the same connection.
2924 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2925 "Host: 172.22.68.17\r\n"
2926 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292927 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2928 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2929 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2930 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2931 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242932 };
2933
2934 MockRead data_reads2[] = {
2935 // The origin server responds with a Type 2 message.
2936 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2937 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292938 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242939 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2940 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2941 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2942 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2943 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2944 "BtAAAAAAA=\r\n"),
2945 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362946 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242947 MockRead("You are not authorized to view this page\r\n"),
2948
2949 // Lastly we get the desired content.
2950 MockRead("HTTP/1.1 200 OK\r\n"),
2951 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2952 MockRead("Content-Length: 13\r\n\r\n"),
2953 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422954 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242955 };
2956
[email protected]31a2bfe2010-02-09 08:03:392957 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2958 data_writes1, arraysize(data_writes1));
2959 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2960 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592961 session_deps.socket_factory.AddSocketDataProvider(&data1);
2962 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242963
[email protected]f1f3f0f82011-10-01 20:38:102964 TestOldCompletionCallback callback1;
[email protected]3f918782009-02-28 01:29:242965
[email protected]0b0bf032010-09-21 18:08:502966 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2967
[email protected]5a1d7ca2010-04-28 20:12:272968 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422969 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242970
2971 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422972 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242973
[email protected]0757e7702009-03-27 04:00:222974 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2975
[email protected]1c773ea12009-04-28 19:58:422976 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:042977 ASSERT_FALSE(response == NULL);
2978 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]3f918782009-02-28 01:29:242979
[email protected]f1f3f0f82011-10-01 20:38:102980 TestOldCompletionCallback callback2;
[email protected]10af5fe72011-01-31 16:17:252981
2982 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
2983 EXPECT_EQ(ERR_IO_PENDING, rv);
2984
2985 rv = callback2.WaitForResult();
2986 EXPECT_EQ(OK, rv);
2987
2988 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2989
2990 response = trans->GetResponseInfo();
2991 ASSERT_TRUE(response != NULL);
[email protected]10af5fe72011-01-31 16:17:252992 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2993
[email protected]f1f3f0f82011-10-01 20:38:102994 TestOldCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242995
[email protected]10af5fe72011-01-31 16:17:252996 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:422997 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242998
[email protected]0757e7702009-03-27 04:00:222999 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423000 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:243001
3002 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503003 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:243004 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3005 EXPECT_EQ(13, response->headers->GetContentLength());
3006}
3007
[email protected]385a4672009-03-11 22:21:293008// Enter a wrong password, and then the correct one.
3009TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:423010 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:293011 request.method = "GET";
3012 request.url = GURL("http://172.22.68.17/kids/login.aspx");
3013 request.load_flags = 0;
3014
[email protected]cb9bf6ca2011-01-28 13:15:273015 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
3016 MockGetHostName);
3017 SessionDependencies session_deps;
3018 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3019
[email protected]385a4672009-03-11 22:21:293020 MockWrite data_writes1[] = {
3021 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3022 "Host: 172.22.68.17\r\n"
3023 "Connection: keep-alive\r\n\r\n"),
3024 };
3025
3026 MockRead data_reads1[] = {
3027 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:043028 // Negotiate and NTLM are often requested together. However, we only want
3029 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
3030 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:293031 MockRead("WWW-Authenticate: NTLM\r\n"),
3032 MockRead("Connection: close\r\n"),
3033 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363034 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293035 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423036 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293037 };
3038
3039 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:223040 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293041 // request we should be issuing -- the final header line contains a Type
3042 // 1 message.
3043 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3044 "Host: 172.22.68.17\r\n"
3045 "Connection: keep-alive\r\n"
3046 "Authorization: NTLM "
3047 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3048
3049 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3050 // (the credentials for the origin server). The second request continues
3051 // on the same connection.
3052 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3053 "Host: 172.22.68.17\r\n"
3054 "Connection: keep-alive\r\n"
3055 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3056 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3057 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
3058 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
3059 "4Ww7b7E=\r\n\r\n"),
3060 };
3061
3062 MockRead data_reads2[] = {
3063 // The origin server responds with a Type 2 message.
3064 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3065 MockRead("WWW-Authenticate: NTLM "
3066 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
3067 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3068 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3069 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3070 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3071 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3072 "BtAAAAAAA=\r\n"),
3073 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363074 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293075 MockRead("You are not authorized to view this page\r\n"),
3076
3077 // Wrong password.
3078 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:293079 MockRead("WWW-Authenticate: NTLM\r\n"),
3080 MockRead("Connection: close\r\n"),
3081 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363082 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293083 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:423084 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:293085 };
3086
3087 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:223088 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:293089 // request we should be issuing -- the final header line contains a Type
3090 // 1 message.
3091 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3092 "Host: 172.22.68.17\r\n"
3093 "Connection: keep-alive\r\n"
3094 "Authorization: NTLM "
3095 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
3096
3097 // After calling trans->RestartWithAuth(), we should send a Type 3 message
3098 // (the credentials for the origin server). The second request continues
3099 // on the same connection.
3100 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
3101 "Host: 172.22.68.17\r\n"
3102 "Connection: keep-alive\r\n"
3103 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
3104 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
3105 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
3106 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
3107 "+4MUm7c=\r\n\r\n"),
3108 };
3109
3110 MockRead data_reads3[] = {
3111 // The origin server responds with a Type 2 message.
3112 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3113 MockRead("WWW-Authenticate: NTLM "
3114 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3115 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3116 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3117 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3118 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3119 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3120 "BtAAAAAAA=\r\n"),
3121 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363122 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293123 MockRead("You are not authorized to view this page\r\n"),
3124
3125 // Lastly we get the desired content.
3126 MockRead("HTTP/1.1 200 OK\r\n"),
3127 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3128 MockRead("Content-Length: 13\r\n\r\n"),
3129 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423130 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293131 };
3132
[email protected]31a2bfe2010-02-09 08:03:393133 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3134 data_writes1, arraysize(data_writes1));
3135 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3136 data_writes2, arraysize(data_writes2));
3137 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3138 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593139 session_deps.socket_factory.AddSocketDataProvider(&data1);
3140 session_deps.socket_factory.AddSocketDataProvider(&data2);
3141 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293142
[email protected]f1f3f0f82011-10-01 20:38:103143 TestOldCompletionCallback callback1;
[email protected]385a4672009-03-11 22:21:293144
[email protected]0b0bf032010-09-21 18:08:503145 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3146
[email protected]5a1d7ca2010-04-28 20:12:273147 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423148 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293149
3150 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423151 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293152
[email protected]0757e7702009-03-27 04:00:223153 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293154
[email protected]1c773ea12009-04-28 19:58:423155 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503156 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043157 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]385a4672009-03-11 22:21:293158
[email protected]f1f3f0f82011-10-01 20:38:103159 TestOldCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293160
[email protected]0757e7702009-03-27 04:00:223161 // Enter the wrong password.
[email protected]10af5fe72011-01-31 16:17:253162 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
[email protected]1c773ea12009-04-28 19:58:423163 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293164
[email protected]10af5fe72011-01-31 16:17:253165 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423166 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293167
[email protected]0757e7702009-03-27 04:00:223168 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:103169 TestOldCompletionCallback callback3;
[email protected]10af5fe72011-01-31 16:17:253170 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423171 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253172 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423173 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223174 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3175
3176 response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:043177 ASSERT_FALSE(response == NULL);
3178 EXPECT_TRUE(CheckNTLMServerAuth(response->auth_challenge.get()));
[email protected]0757e7702009-03-27 04:00:223179
[email protected]f1f3f0f82011-10-01 20:38:103180 TestOldCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223181
3182 // Now enter the right password.
[email protected]10af5fe72011-01-31 16:17:253183 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
3184 EXPECT_EQ(ERR_IO_PENDING, rv);
3185
3186 rv = callback4.WaitForResult();
3187 EXPECT_EQ(OK, rv);
3188
3189 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3190
[email protected]f1f3f0f82011-10-01 20:38:103191 TestOldCompletionCallback callback5;
[email protected]10af5fe72011-01-31 16:17:253192
3193 // One more roundtrip
3194 rv = trans->RestartWithAuth(string16(), string16(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423195 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223196
3197 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423198 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223199
[email protected]385a4672009-03-11 22:21:293200 response = trans->GetResponseInfo();
3201 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3202 EXPECT_EQ(13, response->headers->GetContentLength());
3203}
[email protected]ea9dc9a2009-09-05 00:43:323204#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293205
[email protected]4ddaf2502008-10-23 18:26:193206// Test reading a server response which has only headers, and no body.
3207// After some maximum number of bytes is consumed, the transaction should
3208// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3209TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423210 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193211 request.method = "GET";
3212 request.url = GURL("http://www.google.com/");
3213 request.load_flags = 0;
3214
[email protected]cb9bf6ca2011-01-28 13:15:273215 SessionDependencies session_deps;
3216 scoped_ptr<HttpTransaction> trans(
3217 new HttpNetworkTransaction(CreateSession(&session_deps)));
3218
[email protected]b75b7b2f2009-10-06 00:54:533219 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433220 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533221 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193222
3223 MockRead data_reads[] = {
3224 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433225 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193226 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423227 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193228 };
[email protected]31a2bfe2010-02-09 08:03:393229 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593230 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193231
[email protected]f1f3f0f82011-10-01 20:38:103232 TestOldCompletionCallback callback;
[email protected]4ddaf2502008-10-23 18:26:193233
[email protected]5a1d7ca2010-04-28 20:12:273234 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423235 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193236
3237 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423238 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193239
[email protected]1c773ea12009-04-28 19:58:423240 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193241 EXPECT_TRUE(response == NULL);
3242}
[email protected]f4e426b2008-11-05 00:24:493243
3244// Make sure that we don't try to reuse a TCPClientSocket when failing to
3245// establish tunnel.
3246// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283247TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273248 HttpRequestInfo request;
3249 request.method = "GET";
3250 request.url = GURL("https://www.google.com/");
3251 request.load_flags = 0;
3252
[email protected]f4e426b2008-11-05 00:24:493253 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003254 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013255
[email protected]228ff742009-06-05 01:19:593256 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493257
[email protected]5695b8c2009-09-30 21:36:433258 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493259
[email protected]f4e426b2008-11-05 00:24:493260 // Since we have proxy, should try to establish tunnel.
3261 MockWrite data_writes1[] = {
3262 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453263 "Host: www.google.com\r\n"
3264 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493265 };
3266
[email protected]77848d12008-11-14 00:00:223267 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493268 // connection. Usually a proxy would return 501 (not implemented),
3269 // or 200 (tunnel established).
3270 MockRead data_reads1[] = {
3271 MockRead("HTTP/1.1 404 Not Found\r\n"),
3272 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423273 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493274 };
3275
[email protected]31a2bfe2010-02-09 08:03:393276 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3277 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593278 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493279
[email protected]f1f3f0f82011-10-01 20:38:103280 TestOldCompletionCallback callback1;
[email protected]f4e426b2008-11-05 00:24:493281
[email protected]5a1d7ca2010-04-28 20:12:273282 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423283 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493284
3285 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423286 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493287
[email protected]1c773ea12009-04-28 19:58:423288 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083289 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493290
[email protected]b4404c02009-04-10 16:38:523291 // Empty the current queue. This is necessary because idle sockets are
3292 // added to the connection pool asynchronously with a PostTask.
3293 MessageLoop::current()->RunAllPending();
3294
[email protected]f4e426b2008-11-05 00:24:493295 // We now check to make sure the TCPClientSocket was not added back to
3296 // the pool.
[email protected]ab739042011-04-07 15:22:283297 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493298 trans.reset();
[email protected]b4404c02009-04-10 16:38:523299 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493300 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]ab739042011-04-07 15:22:283301 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493302}
[email protected]372d34a2008-11-05 21:30:513303
[email protected]1b157c02009-04-21 01:55:403304// Make sure that we recycle a socket after reading all of the response body.
3305TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423306 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403307 request.method = "GET";
3308 request.url = GURL("http://www.google.com/");
3309 request.load_flags = 0;
3310
[email protected]cb9bf6ca2011-01-28 13:15:273311 SessionDependencies session_deps;
3312 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3313
3314 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3315
[email protected]1b157c02009-04-21 01:55:403316 MockRead data_reads[] = {
3317 // A part of the response body is received with the response headers.
3318 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3319 // The rest of the response body is received in two parts.
3320 MockRead("lo"),
3321 MockRead(" world"),
3322 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423323 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403324 };
3325
[email protected]31a2bfe2010-02-09 08:03:393326 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593327 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403328
[email protected]f1f3f0f82011-10-01 20:38:103329 TestOldCompletionCallback callback;
[email protected]1b157c02009-04-21 01:55:403330
[email protected]5a1d7ca2010-04-28 20:12:273331 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423332 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403333
3334 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423335 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403336
[email protected]1c773ea12009-04-28 19:58:423337 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503338 ASSERT_TRUE(response != NULL);
[email protected]1b157c02009-04-21 01:55:403339
3340 EXPECT_TRUE(response->headers != NULL);
3341 std::string status_line = response->headers->GetStatusLine();
3342 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3343
[email protected]ab739042011-04-07 15:22:283344 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403345
3346 std::string response_data;
3347 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423348 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403349 EXPECT_EQ("hello world", response_data);
3350
3351 // Empty the current queue. This is necessary because idle sockets are
3352 // added to the connection pool asynchronously with a PostTask.
3353 MessageLoop::current()->RunAllPending();
3354
3355 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283356 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403357}
3358
[email protected]76a505b2010-08-25 06:23:003359// Make sure that we recycle a SSL socket after reading all of the response
3360// body.
3361TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3362 SessionDependencies session_deps;
3363 HttpRequestInfo request;
3364 request.method = "GET";
3365 request.url = GURL("https://www.google.com/");
3366 request.load_flags = 0;
3367
3368 MockWrite data_writes[] = {
3369 MockWrite("GET / HTTP/1.1\r\n"
3370 "Host: www.google.com\r\n"
3371 "Connection: keep-alive\r\n\r\n"),
3372 };
3373
3374 MockRead data_reads[] = {
3375 MockRead("HTTP/1.1 200 OK\r\n"),
3376 MockRead("Content-Length: 11\r\n\r\n"),
3377 MockRead("hello world"),
3378 MockRead(false, OK),
3379 };
3380
3381 SSLSocketDataProvider ssl(true, OK);
3382 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3383
3384 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3385 data_writes, arraysize(data_writes));
3386 session_deps.socket_factory.AddSocketDataProvider(&data);
3387
[email protected]f1f3f0f82011-10-01 20:38:103388 TestOldCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003389
3390 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3391 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3392
3393 int rv = trans->Start(&request, &callback, BoundNetLog());
3394
3395 EXPECT_EQ(ERR_IO_PENDING, rv);
3396 EXPECT_EQ(OK, callback.WaitForResult());
3397
3398 const HttpResponseInfo* response = trans->GetResponseInfo();
3399 ASSERT_TRUE(response != NULL);
3400 ASSERT_TRUE(response->headers != NULL);
3401 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3402
[email protected]ab739042011-04-07 15:22:283403 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003404
3405 std::string response_data;
3406 rv = ReadTransaction(trans.get(), &response_data);
3407 EXPECT_EQ(OK, rv);
3408 EXPECT_EQ("hello world", response_data);
3409
3410 // Empty the current queue. This is necessary because idle sockets are
3411 // added to the connection pool asynchronously with a PostTask.
3412 MessageLoop::current()->RunAllPending();
3413
3414 // We now check to make sure the socket was added back to the pool.
3415 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3416}
3417
3418// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3419// from the pool and make sure that we recover okay.
3420TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3421 SessionDependencies session_deps;
3422 HttpRequestInfo request;
3423 request.method = "GET";
3424 request.url = GURL("https://www.google.com/");
3425 request.load_flags = 0;
3426
3427 MockWrite data_writes[] = {
3428 MockWrite("GET / HTTP/1.1\r\n"
3429 "Host: www.google.com\r\n"
3430 "Connection: keep-alive\r\n\r\n"),
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(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3440 MockRead("hello world"),
3441 MockRead(true, 0, 0) // EOF
3442 };
3443
3444 SSLSocketDataProvider ssl(true, OK);
3445 SSLSocketDataProvider ssl2(true, OK);
3446 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3447 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3448
3449 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3450 data_writes, arraysize(data_writes));
3451 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3452 data_writes, arraysize(data_writes));
3453 session_deps.socket_factory.AddSocketDataProvider(&data);
3454 session_deps.socket_factory.AddSocketDataProvider(&data2);
3455
[email protected]f1f3f0f82011-10-01 20:38:103456 TestOldCompletionCallback callback;
[email protected]76a505b2010-08-25 06:23:003457
3458 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3459 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3460
3461 int rv = trans->Start(&request, &callback, BoundNetLog());
3462
3463 EXPECT_EQ(ERR_IO_PENDING, rv);
3464 EXPECT_EQ(OK, callback.WaitForResult());
3465
3466 const HttpResponseInfo* response = trans->GetResponseInfo();
3467 ASSERT_TRUE(response != NULL);
3468 ASSERT_TRUE(response->headers != NULL);
3469 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3470
[email protected]ab739042011-04-07 15:22:283471 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003472
3473 std::string response_data;
3474 rv = ReadTransaction(trans.get(), &response_data);
3475 EXPECT_EQ(OK, rv);
3476 EXPECT_EQ("hello world", response_data);
3477
3478 // Empty the current queue. This is necessary because idle sockets are
3479 // added to the connection pool asynchronously with a PostTask.
3480 MessageLoop::current()->RunAllPending();
3481
3482 // We now check to make sure the socket was added back to the pool.
3483 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3484
3485 // Now start the second transaction, which should reuse the previous socket.
3486
3487 trans.reset(new HttpNetworkTransaction(session));
3488
3489 rv = trans->Start(&request, &callback, BoundNetLog());
3490
3491 EXPECT_EQ(ERR_IO_PENDING, rv);
3492 EXPECT_EQ(OK, callback.WaitForResult());
3493
3494 response = trans->GetResponseInfo();
3495 ASSERT_TRUE(response != NULL);
3496 ASSERT_TRUE(response->headers != NULL);
3497 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3498
[email protected]ab739042011-04-07 15:22:283499 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003500
3501 rv = ReadTransaction(trans.get(), &response_data);
3502 EXPECT_EQ(OK, rv);
3503 EXPECT_EQ("hello world", response_data);
3504
3505 // Empty the current queue. This is necessary because idle sockets are
3506 // added to the connection pool asynchronously with a PostTask.
3507 MessageLoop::current()->RunAllPending();
3508
3509 // We now check to make sure the socket was added back to the pool.
3510 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3511}
3512
[email protected]b4404c02009-04-10 16:38:523513// Make sure that we recycle a socket after a zero-length response.
3514// http://crbug.com/9880
3515TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423516 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523517 request.method = "GET";
3518 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3519 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3520 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3521 "rt=prt.2642,ol.2649,xjs.2951");
3522 request.load_flags = 0;
3523
[email protected]cb9bf6ca2011-01-28 13:15:273524 SessionDependencies session_deps;
3525 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3526
3527 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3528
[email protected]b4404c02009-04-10 16:38:523529 MockRead data_reads[] = {
3530 MockRead("HTTP/1.1 204 No Content\r\n"
3531 "Content-Length: 0\r\n"
3532 "Content-Type: text/html\r\n\r\n"),
3533 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423534 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523535 };
3536
[email protected]31a2bfe2010-02-09 08:03:393537 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593538 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523539
[email protected]f1f3f0f82011-10-01 20:38:103540 TestOldCompletionCallback callback;
[email protected]b4404c02009-04-10 16:38:523541
[email protected]5a1d7ca2010-04-28 20:12:273542 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423543 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523544
3545 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423546 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523547
[email protected]1c773ea12009-04-28 19:58:423548 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503549 ASSERT_TRUE(response != NULL);
[email protected]b4404c02009-04-10 16:38:523550
3551 EXPECT_TRUE(response->headers != NULL);
3552 std::string status_line = response->headers->GetStatusLine();
3553 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3554
[email protected]ab739042011-04-07 15:22:283555 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523556
3557 std::string response_data;
3558 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423559 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523560 EXPECT_EQ("", response_data);
3561
3562 // Empty the current queue. This is necessary because idle sockets are
3563 // added to the connection pool asynchronously with a PostTask.
3564 MessageLoop::current()->RunAllPending();
3565
3566 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283567 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523568}
3569
[email protected]372d34a2008-11-05 21:30:513570TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423571 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513572 // Transaction 1: a GET request that succeeds. The socket is recycled
3573 // after use.
3574 request[0].method = "GET";
3575 request[0].url = GURL("http://www.google.com/");
3576 request[0].load_flags = 0;
3577 // Transaction 2: a POST request. Reuses the socket kept alive from
3578 // transaction 1. The first attempts fails when writing the POST data.
3579 // This causes the transaction to retry with a new socket. The second
3580 // attempt succeeds.
3581 request[1].method = "POST";
3582 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423583 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513584 request[1].upload_data->AppendBytes("foo", 3);
3585 request[1].load_flags = 0;
3586
[email protected]228ff742009-06-05 01:19:593587 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273588 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513589
3590 // The first socket is used for transaction 1 and the first attempt of
3591 // transaction 2.
3592
3593 // The response of transaction 1.
3594 MockRead data_reads1[] = {
3595 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3596 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423597 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513598 };
3599 // The mock write results of transaction 1 and the first attempt of
3600 // transaction 2.
3601 MockWrite data_writes1[] = {
3602 MockWrite(false, 64), // GET
3603 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423604 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513605 };
[email protected]31a2bfe2010-02-09 08:03:393606 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3607 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513608
3609 // The second socket is used for the second attempt of transaction 2.
3610
3611 // The response of transaction 2.
3612 MockRead data_reads2[] = {
3613 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3614 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423615 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513616 };
3617 // The mock write results of the second attempt of transaction 2.
3618 MockWrite data_writes2[] = {
3619 MockWrite(false, 93), // POST
3620 MockWrite(false, 3), // POST data
3621 };
[email protected]31a2bfe2010-02-09 08:03:393622 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3623 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513624
[email protected]5ecc992a42009-11-11 01:41:593625 session_deps.socket_factory.AddSocketDataProvider(&data1);
3626 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513627
3628 const char* kExpectedResponseData[] = {
3629 "hello world", "welcome"
3630 };
3631
3632 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423633 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433634 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513635
[email protected]f1f3f0f82011-10-01 20:38:103636 TestOldCompletionCallback callback;
[email protected]372d34a2008-11-05 21:30:513637
[email protected]5a1d7ca2010-04-28 20:12:273638 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423639 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513640
3641 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423642 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513643
[email protected]1c773ea12009-04-28 19:58:423644 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503645 ASSERT_TRUE(response != NULL);
[email protected]372d34a2008-11-05 21:30:513646
3647 EXPECT_TRUE(response->headers != NULL);
3648 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3649
3650 std::string response_data;
3651 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423652 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513653 EXPECT_EQ(kExpectedResponseData[i], response_data);
3654 }
3655}
[email protected]f9ee6b52008-11-08 06:46:233656
3657// Test the request-challenge-retry sequence for basic auth when there is
3658// an identity in the URL. The request should be sent as normal, but when
3659// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323660TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423661 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233662 request.method = "GET";
3663 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293664 request.url = GURL("http://foo:b@[email protected]/");
3665
[email protected]cb9bf6ca2011-01-28 13:15:273666 SessionDependencies session_deps;
3667 scoped_ptr<HttpTransaction> trans(
3668 new HttpNetworkTransaction(CreateSession(&session_deps)));
3669
[email protected]a97cca42009-08-14 01:00:293670 // The password contains an escaped character -- for this test to pass it
3671 // will need to be unescaped by HttpNetworkTransaction.
3672 EXPECT_EQ("b%40r", request.url.password());
3673
[email protected]ea9dc9a2009-09-05 00:43:323674 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233675
3676 MockWrite data_writes1[] = {
3677 MockWrite("GET / HTTP/1.1\r\n"
3678 "Host: www.google.com\r\n"
3679 "Connection: keep-alive\r\n\r\n"),
3680 };
3681
3682 MockRead data_reads1[] = {
3683 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3684 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3685 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423686 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233687 };
3688
3689 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323690 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233691 MockWrite data_writes2[] = {
3692 MockWrite("GET / HTTP/1.1\r\n"
3693 "Host: www.google.com\r\n"
3694 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293695 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233696 };
3697
3698 MockRead data_reads2[] = {
3699 MockRead("HTTP/1.0 200 OK\r\n"),
3700 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423701 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233702 };
3703
[email protected]31a2bfe2010-02-09 08:03:393704 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3705 data_writes1, arraysize(data_writes1));
3706 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3707 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593708 session_deps.socket_factory.AddSocketDataProvider(&data1);
3709 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233710
[email protected]f1f3f0f82011-10-01 20:38:103711 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233712
[email protected]5a1d7ca2010-04-28 20:12:273713 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423714 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233715
3716 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423717 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233718
[email protected]0757e7702009-03-27 04:00:223719 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:103720 TestOldCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443721 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423722 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223723 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423724 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223725 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3726
[email protected]1c773ea12009-04-28 19:58:423727 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503728 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233729
3730 // There is no challenge info, since the identity in URL worked.
3731 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3732
3733 EXPECT_EQ(100, response->headers->GetContentLength());
3734
3735 // Empty the current queue.
3736 MessageLoop::current()->RunAllPending();
3737}
3738
[email protected]ea9dc9a2009-09-05 00:43:323739// Test the request-challenge-retry sequence for basic auth when there is
3740// an incorrect identity in the URL. The identity from the URL should be used
3741// only once.
3742TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323743 HttpRequestInfo request;
3744 request.method = "GET";
3745 // Note: the URL has a username:password in it. The password "baz" is
3746 // wrong (should be "bar").
3747 request.url = GURL("http://foo:[email protected]/");
3748
3749 request.load_flags = LOAD_NORMAL;
3750
[email protected]cb9bf6ca2011-01-28 13:15:273751 SessionDependencies session_deps;
3752 scoped_ptr<HttpTransaction> trans(
3753 new HttpNetworkTransaction(CreateSession(&session_deps)));
3754
[email protected]ea9dc9a2009-09-05 00:43:323755 MockWrite data_writes1[] = {
3756 MockWrite("GET / HTTP/1.1\r\n"
3757 "Host: www.google.com\r\n"
3758 "Connection: keep-alive\r\n\r\n"),
3759 };
3760
3761 MockRead data_reads1[] = {
3762 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3763 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3764 MockRead("Content-Length: 10\r\n\r\n"),
3765 MockRead(false, ERR_FAILED),
3766 };
3767
3768 // After the challenge above, the transaction will be restarted using the
3769 // identity from the url (foo, baz) to answer the challenge.
3770 MockWrite data_writes2[] = {
3771 MockWrite("GET / HTTP/1.1\r\n"
3772 "Host: www.google.com\r\n"
3773 "Connection: keep-alive\r\n"
3774 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3775 };
3776
3777 MockRead data_reads2[] = {
3778 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3779 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3780 MockRead("Content-Length: 10\r\n\r\n"),
3781 MockRead(false, ERR_FAILED),
3782 };
3783
3784 // After the challenge above, the transaction will be restarted using the
3785 // identity supplied by the user (foo, bar) to answer the challenge.
3786 MockWrite data_writes3[] = {
3787 MockWrite("GET / HTTP/1.1\r\n"
3788 "Host: www.google.com\r\n"
3789 "Connection: keep-alive\r\n"
3790 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3791 };
3792
3793 MockRead data_reads3[] = {
3794 MockRead("HTTP/1.0 200 OK\r\n"),
3795 MockRead("Content-Length: 100\r\n\r\n"),
3796 MockRead(false, OK),
3797 };
3798
[email protected]31a2bfe2010-02-09 08:03:393799 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3800 data_writes1, arraysize(data_writes1));
3801 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3802 data_writes2, arraysize(data_writes2));
3803 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3804 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593805 session_deps.socket_factory.AddSocketDataProvider(&data1);
3806 session_deps.socket_factory.AddSocketDataProvider(&data2);
3807 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323808
[email protected]f1f3f0f82011-10-01 20:38:103809 TestOldCompletionCallback callback1;
[email protected]ea9dc9a2009-09-05 00:43:323810
[email protected]5a1d7ca2010-04-28 20:12:273811 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323812 EXPECT_EQ(ERR_IO_PENDING, rv);
3813
3814 rv = callback1.WaitForResult();
3815 EXPECT_EQ(OK, rv);
3816
3817 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:103818 TestOldCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443819 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323820 EXPECT_EQ(ERR_IO_PENDING, rv);
3821 rv = callback2.WaitForResult();
3822 EXPECT_EQ(OK, rv);
3823 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3824
3825 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503826 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043827 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]ea9dc9a2009-09-05 00:43:323828
[email protected]f1f3f0f82011-10-01 20:38:103829 TestOldCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443830 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323831 EXPECT_EQ(ERR_IO_PENDING, rv);
3832 rv = callback3.WaitForResult();
3833 EXPECT_EQ(OK, rv);
3834 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3835
3836 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503837 ASSERT_TRUE(response != NULL);
[email protected]ea9dc9a2009-09-05 00:43:323838
3839 // There is no challenge info, since the identity worked.
3840 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3841
3842 EXPECT_EQ(100, response->headers->GetContentLength());
3843
3844 // Empty the current queue.
3845 MessageLoop::current()->RunAllPending();
3846}
3847
[email protected]f9ee6b52008-11-08 06:46:233848// Test that previously tried username/passwords for a realm get re-used.
3849TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593850 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273851 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233852
3853 // Transaction 1: authenticate (foo, bar) on MyRealm1
3854 {
[email protected]1c773ea12009-04-28 19:58:423855 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233856 request.method = "GET";
3857 request.url = GURL("http://www.google.com/x/y/z");
3858 request.load_flags = 0;
3859
[email protected]cb9bf6ca2011-01-28 13:15:273860 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3861
[email protected]f9ee6b52008-11-08 06:46:233862 MockWrite data_writes1[] = {
3863 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3864 "Host: www.google.com\r\n"
3865 "Connection: keep-alive\r\n\r\n"),
3866 };
3867
3868 MockRead data_reads1[] = {
3869 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3870 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3871 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423872 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233873 };
3874
3875 // Resend with authorization (username=foo, password=bar)
3876 MockWrite data_writes2[] = {
3877 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3878 "Host: www.google.com\r\n"
3879 "Connection: keep-alive\r\n"
3880 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3881 };
3882
3883 // Sever accepts the authorization.
3884 MockRead data_reads2[] = {
3885 MockRead("HTTP/1.0 200 OK\r\n"),
3886 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423887 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233888 };
3889
[email protected]31a2bfe2010-02-09 08:03:393890 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3891 data_writes1, arraysize(data_writes1));
3892 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3893 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593894 session_deps.socket_factory.AddSocketDataProvider(&data1);
3895 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233896
[email protected]f1f3f0f82011-10-01 20:38:103897 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233898
[email protected]5a1d7ca2010-04-28 20:12:273899 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423900 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233901
3902 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423903 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233904
[email protected]1c773ea12009-04-28 19:58:423905 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503906 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043907 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:233908
[email protected]f1f3f0f82011-10-01 20:38:103909 TestOldCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233910
[email protected]13c8a092010-07-29 06:15:443911 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423912 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233913
3914 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423915 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233916
3917 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503918 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:233919 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3920 EXPECT_EQ(100, response->headers->GetContentLength());
3921 }
3922
3923 // ------------------------------------------------------------------------
3924
3925 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3926 {
[email protected]1c773ea12009-04-28 19:58:423927 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233928 request.method = "GET";
3929 // Note that Transaction 1 was at /x/y/z, so this is in the same
3930 // protection space as MyRealm1.
3931 request.url = GURL("http://www.google.com/x/y/a/b");
3932 request.load_flags = 0;
3933
[email protected]cb9bf6ca2011-01-28 13:15:273934 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3935
[email protected]f9ee6b52008-11-08 06:46:233936 MockWrite data_writes1[] = {
3937 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3938 "Host: www.google.com\r\n"
3939 "Connection: keep-alive\r\n"
3940 // Send preemptive authorization for MyRealm1
3941 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3942 };
3943
3944 // The server didn't like the preemptive authorization, and
3945 // challenges us for a different realm (MyRealm2).
3946 MockRead data_reads1[] = {
3947 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3948 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3949 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423950 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233951 };
3952
3953 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3954 MockWrite data_writes2[] = {
3955 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3956 "Host: www.google.com\r\n"
3957 "Connection: keep-alive\r\n"
3958 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3959 };
3960
3961 // Sever accepts the authorization.
3962 MockRead data_reads2[] = {
3963 MockRead("HTTP/1.0 200 OK\r\n"),
3964 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423965 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233966 };
3967
[email protected]31a2bfe2010-02-09 08:03:393968 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3969 data_writes1, arraysize(data_writes1));
3970 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3971 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593972 session_deps.socket_factory.AddSocketDataProvider(&data1);
3973 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233974
[email protected]f1f3f0f82011-10-01 20:38:103975 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:233976
[email protected]5a1d7ca2010-04-28 20:12:273977 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423978 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233979
3980 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423981 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233982
[email protected]1c773ea12009-04-28 19:58:423983 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:503984 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:043985 ASSERT_TRUE(response->auth_challenge.get());
3986 EXPECT_FALSE(response->auth_challenge->is_proxy);
3987 EXPECT_EQ("www.google.com:80",
3988 response->auth_challenge->challenger.ToString());
3989 EXPECT_EQ("MyRealm2", response->auth_challenge->realm);
3990 EXPECT_EQ("basic", response->auth_challenge->scheme);
[email protected]f9ee6b52008-11-08 06:46:233991
[email protected]f1f3f0f82011-10-01 20:38:103992 TestOldCompletionCallback callback2;
[email protected]f9ee6b52008-11-08 06:46:233993
[email protected]13c8a092010-07-29 06:15:443994 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423995 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233996
3997 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423998 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233999
4000 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504001 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234002 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4003 EXPECT_EQ(100, response->headers->GetContentLength());
4004 }
4005
4006 // ------------------------------------------------------------------------
4007
4008 // Transaction 3: Resend a request in MyRealm's protection space --
4009 // succeed with preemptive authorization.
4010 {
[email protected]1c773ea12009-04-28 19:58:424011 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234012 request.method = "GET";
4013 request.url = GURL("http://www.google.com/x/y/z2");
4014 request.load_flags = 0;
4015
[email protected]cb9bf6ca2011-01-28 13:15:274016 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4017
[email protected]f9ee6b52008-11-08 06:46:234018 MockWrite data_writes1[] = {
4019 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
4020 "Host: www.google.com\r\n"
4021 "Connection: keep-alive\r\n"
4022 // The authorization for MyRealm1 gets sent preemptively
4023 // (since the url is in the same protection space)
4024 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4025 };
4026
4027 // Sever accepts the preemptive authorization
4028 MockRead data_reads1[] = {
4029 MockRead("HTTP/1.0 200 OK\r\n"),
4030 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424031 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234032 };
4033
[email protected]31a2bfe2010-02-09 08:03:394034 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4035 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:594036 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:234037
[email protected]f1f3f0f82011-10-01 20:38:104038 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234039
[email protected]5a1d7ca2010-04-28 20:12:274040 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424041 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234042
4043 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424044 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234045
[email protected]1c773ea12009-04-28 19:58:424046 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504047 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234048
4049 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4050 EXPECT_EQ(100, response->headers->GetContentLength());
4051 }
4052
4053 // ------------------------------------------------------------------------
4054
4055 // Transaction 4: request another URL in MyRealm (however the
4056 // url is not known to belong to the protection space, so no pre-auth).
4057 {
[email protected]1c773ea12009-04-28 19:58:424058 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234059 request.method = "GET";
4060 request.url = GURL("http://www.google.com/x/1");
4061 request.load_flags = 0;
4062
[email protected]cb9bf6ca2011-01-28 13:15:274063 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4064
[email protected]f9ee6b52008-11-08 06:46:234065 MockWrite data_writes1[] = {
4066 MockWrite("GET /x/1 HTTP/1.1\r\n"
4067 "Host: www.google.com\r\n"
4068 "Connection: keep-alive\r\n\r\n"),
4069 };
4070
4071 MockRead data_reads1[] = {
4072 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4073 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4074 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424075 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234076 };
4077
4078 // Resend with authorization from MyRealm's cache.
4079 MockWrite data_writes2[] = {
4080 MockWrite("GET /x/1 HTTP/1.1\r\n"
4081 "Host: www.google.com\r\n"
4082 "Connection: keep-alive\r\n"
4083 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4084 };
4085
4086 // Sever accepts the authorization.
4087 MockRead data_reads2[] = {
4088 MockRead("HTTP/1.0 200 OK\r\n"),
4089 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424090 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234091 };
4092
[email protected]31a2bfe2010-02-09 08:03:394093 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4094 data_writes1, arraysize(data_writes1));
4095 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4096 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594097 session_deps.socket_factory.AddSocketDataProvider(&data1);
4098 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234099
[email protected]f1f3f0f82011-10-01 20:38:104100 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234101
[email protected]5a1d7ca2010-04-28 20:12:274102 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424103 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234104
4105 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424106 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234107
[email protected]0757e7702009-03-27 04:00:224108 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:104109 TestOldCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444110 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424111 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224112 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424113 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224114 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4115
[email protected]1c773ea12009-04-28 19:58:424116 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504117 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234118 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4119 EXPECT_EQ(100, response->headers->GetContentLength());
4120 }
4121
4122 // ------------------------------------------------------------------------
4123
4124 // Transaction 5: request a URL in MyRealm, but the server rejects the
4125 // cached identity. Should invalidate and re-prompt.
4126 {
[email protected]1c773ea12009-04-28 19:58:424127 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234128 request.method = "GET";
4129 request.url = GURL("http://www.google.com/p/q/t");
4130 request.load_flags = 0;
4131
[email protected]cb9bf6ca2011-01-28 13:15:274132 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4133
[email protected]f9ee6b52008-11-08 06:46:234134 MockWrite data_writes1[] = {
4135 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4136 "Host: www.google.com\r\n"
4137 "Connection: keep-alive\r\n\r\n"),
4138 };
4139
4140 MockRead data_reads1[] = {
4141 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4142 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4143 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424144 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234145 };
4146
4147 // Resend with authorization from cache for MyRealm.
4148 MockWrite data_writes2[] = {
4149 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4150 "Host: www.google.com\r\n"
4151 "Connection: keep-alive\r\n"
4152 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4153 };
4154
4155 // Sever rejects the authorization.
4156 MockRead data_reads2[] = {
4157 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4158 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4159 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424160 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234161 };
4162
4163 // At this point we should prompt for new credentials for MyRealm.
4164 // Restart with username=foo3, password=foo4.
4165 MockWrite data_writes3[] = {
4166 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4167 "Host: www.google.com\r\n"
4168 "Connection: keep-alive\r\n"
4169 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4170 };
4171
4172 // Sever accepts the authorization.
4173 MockRead data_reads3[] = {
4174 MockRead("HTTP/1.0 200 OK\r\n"),
4175 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424176 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234177 };
4178
[email protected]31a2bfe2010-02-09 08:03:394179 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4180 data_writes1, arraysize(data_writes1));
4181 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4182 data_writes2, arraysize(data_writes2));
4183 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4184 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594185 session_deps.socket_factory.AddSocketDataProvider(&data1);
4186 session_deps.socket_factory.AddSocketDataProvider(&data2);
4187 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234188
[email protected]f1f3f0f82011-10-01 20:38:104189 TestOldCompletionCallback callback1;
[email protected]f9ee6b52008-11-08 06:46:234190
[email protected]5a1d7ca2010-04-28 20:12:274191 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424192 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234193
4194 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424195 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234196
[email protected]0757e7702009-03-27 04:00:224197 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]f1f3f0f82011-10-01 20:38:104198 TestOldCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444199 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424200 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224201 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424202 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224203 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4204
[email protected]1c773ea12009-04-28 19:58:424205 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504206 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044207 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]f9ee6b52008-11-08 06:46:234208
[email protected]f1f3f0f82011-10-01 20:38:104209 TestOldCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234210
[email protected]13c8a092010-07-29 06:15:444211 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424212 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234213
[email protected]0757e7702009-03-27 04:00:224214 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424215 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234216
4217 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504218 ASSERT_TRUE(response != NULL);
[email protected]f9ee6b52008-11-08 06:46:234219 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4220 EXPECT_EQ(100, response->headers->GetContentLength());
4221 }
4222}
[email protected]89ceba9a2009-03-21 03:46:064223
[email protected]3c32c5f2010-05-18 15:18:124224// Tests that nonce count increments when multiple auth attempts
4225// are started with the same nonce.
4226TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4227 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444228 HttpAuthHandlerDigest::Factory* digest_factory =
4229 new HttpAuthHandlerDigest::Factory();
4230 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4231 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4232 digest_factory->set_nonce_generator(nonce_generator);
4233 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274234 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124235
4236 // Transaction 1: authenticate (foo, bar) on MyRealm1
4237 {
[email protected]3c32c5f2010-05-18 15:18:124238 HttpRequestInfo request;
4239 request.method = "GET";
4240 request.url = GURL("http://www.google.com/x/y/z");
4241 request.load_flags = 0;
4242
[email protected]cb9bf6ca2011-01-28 13:15:274243 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4244
[email protected]3c32c5f2010-05-18 15:18:124245 MockWrite data_writes1[] = {
4246 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4247 "Host: www.google.com\r\n"
4248 "Connection: keep-alive\r\n\r\n"),
4249 };
4250
4251 MockRead data_reads1[] = {
4252 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4253 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4254 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4255 MockRead(false, OK),
4256 };
4257
4258 // Resend with authorization (username=foo, password=bar)
4259 MockWrite data_writes2[] = {
4260 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4261 "Host: www.google.com\r\n"
4262 "Connection: keep-alive\r\n"
4263 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4264 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4265 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4266 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4267 };
4268
4269 // Sever accepts the authorization.
4270 MockRead data_reads2[] = {
4271 MockRead("HTTP/1.0 200 OK\r\n"),
4272 MockRead(false, OK),
4273 };
4274
4275 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4276 data_writes1, arraysize(data_writes1));
4277 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4278 data_writes2, arraysize(data_writes2));
4279 session_deps.socket_factory.AddSocketDataProvider(&data1);
4280 session_deps.socket_factory.AddSocketDataProvider(&data2);
4281
[email protected]f1f3f0f82011-10-01 20:38:104282 TestOldCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124283
4284 int rv = trans->Start(&request, &callback1, BoundNetLog());
4285 EXPECT_EQ(ERR_IO_PENDING, rv);
4286
4287 rv = callback1.WaitForResult();
4288 EXPECT_EQ(OK, rv);
4289
4290 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504291 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:044292 EXPECT_TRUE(CheckDigestServerAuth(response->auth_challenge.get()));
[email protected]3c32c5f2010-05-18 15:18:124293
[email protected]f1f3f0f82011-10-01 20:38:104294 TestOldCompletionCallback callback2;
[email protected]3c32c5f2010-05-18 15:18:124295
[email protected]13c8a092010-07-29 06:15:444296 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124297 EXPECT_EQ(ERR_IO_PENDING, rv);
4298
4299 rv = callback2.WaitForResult();
4300 EXPECT_EQ(OK, rv);
4301
4302 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504303 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124304 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4305 }
4306
4307 // ------------------------------------------------------------------------
4308
4309 // Transaction 2: Request another resource in digestive's protection space.
4310 // This will preemptively add an Authorization header which should have an
4311 // "nc" value of 2 (as compared to 1 in the first use.
4312 {
[email protected]3c32c5f2010-05-18 15:18:124313 HttpRequestInfo request;
4314 request.method = "GET";
4315 // Note that Transaction 1 was at /x/y/z, so this is in the same
4316 // protection space as digest.
4317 request.url = GURL("http://www.google.com/x/y/a/b");
4318 request.load_flags = 0;
4319
[email protected]cb9bf6ca2011-01-28 13:15:274320 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4321
[email protected]3c32c5f2010-05-18 15:18:124322 MockWrite data_writes1[] = {
4323 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4324 "Host: www.google.com\r\n"
4325 "Connection: keep-alive\r\n"
4326 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4327 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4328 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4329 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4330 };
4331
4332 // Sever accepts the authorization.
4333 MockRead data_reads1[] = {
4334 MockRead("HTTP/1.0 200 OK\r\n"),
4335 MockRead("Content-Length: 100\r\n\r\n"),
4336 MockRead(false, OK),
4337 };
4338
4339 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4340 data_writes1, arraysize(data_writes1));
4341 session_deps.socket_factory.AddSocketDataProvider(&data1);
4342
[email protected]f1f3f0f82011-10-01 20:38:104343 TestOldCompletionCallback callback1;
[email protected]3c32c5f2010-05-18 15:18:124344
4345 int rv = trans->Start(&request, &callback1, BoundNetLog());
4346 EXPECT_EQ(ERR_IO_PENDING, rv);
4347
4348 rv = callback1.WaitForResult();
4349 EXPECT_EQ(OK, rv);
4350
4351 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:504352 ASSERT_TRUE(response != NULL);
[email protected]3c32c5f2010-05-18 15:18:124353 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4354 }
4355}
4356
[email protected]89ceba9a2009-03-21 03:46:064357// Test the ResetStateForRestart() private method.
4358TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4359 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594360 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404361 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434362 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064363
4364 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064365 trans->read_buf_ = new IOBuffer(15);
4366 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204367 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064368
4369 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144370 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574371 response->auth_challenge = new AuthChallengeInfo();
[email protected]70d66502011-09-23 00:55:084372 response->ssl_info.cert_status = static_cast<CertStatus>(-1); // Nonsensical.
[email protected]0877e3d2009-10-17 22:29:574373 response->response_time = base::Time::Now();
4374 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064375
4376 { // Setup state for response_.vary_data
4377 HttpRequestInfo request;
4378 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4379 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274380 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434381 request.extra_headers.SetHeader("Foo", "1");
4382 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574383 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064384 }
4385
4386 // Cause the above state to be reset.
4387 trans->ResetStateForRestart();
4388
4389 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074390 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064391 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204392 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574393 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4394 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044395 EXPECT_FALSE(response->was_cached);
[email protected]70d66502011-09-23 00:55:084396 EXPECT_EQ(0U, response->ssl_info.cert_status);
[email protected]0877e3d2009-10-17 22:29:574397 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064398}
4399
[email protected]bacff652009-03-31 17:50:334400// Test HTTPS connections to a site with a bad certificate
4401TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334402 HttpRequestInfo request;
4403 request.method = "GET";
4404 request.url = GURL("https://www.google.com/");
4405 request.load_flags = 0;
4406
[email protected]cb9bf6ca2011-01-28 13:15:274407 SessionDependencies session_deps;
4408 scoped_ptr<HttpTransaction> trans(
4409 new HttpNetworkTransaction(CreateSession(&session_deps)));
4410
[email protected]bacff652009-03-31 17:50:334411 MockWrite data_writes[] = {
4412 MockWrite("GET / HTTP/1.1\r\n"
4413 "Host: www.google.com\r\n"
4414 "Connection: keep-alive\r\n\r\n"),
4415 };
4416
4417 MockRead data_reads[] = {
4418 MockRead("HTTP/1.0 200 OK\r\n"),
4419 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4420 MockRead("Content-Length: 100\r\n\r\n"),
4421 MockRead(false, OK),
4422 };
4423
[email protected]5ecc992a42009-11-11 01:41:594424 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394425 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4426 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594427 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4428 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334429
[email protected]5ecc992a42009-11-11 01:41:594430 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4431 session_deps.socket_factory.AddSocketDataProvider(&data);
4432 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4433 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334434
[email protected]f1f3f0f82011-10-01 20:38:104435 TestOldCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334436
[email protected]5a1d7ca2010-04-28 20:12:274437 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334438 EXPECT_EQ(ERR_IO_PENDING, rv);
4439
4440 rv = callback.WaitForResult();
4441 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4442
4443 rv = trans->RestartIgnoringLastError(&callback);
4444 EXPECT_EQ(ERR_IO_PENDING, rv);
4445
4446 rv = callback.WaitForResult();
4447 EXPECT_EQ(OK, rv);
4448
4449 const HttpResponseInfo* response = trans->GetResponseInfo();
4450
[email protected]fe2255a2011-09-20 19:37:504451 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334452 EXPECT_EQ(100, response->headers->GetContentLength());
4453}
4454
4455// Test HTTPS connections to a site with a bad certificate, going through a
4456// proxy
4457TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004458 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334459
4460 HttpRequestInfo request;
4461 request.method = "GET";
4462 request.url = GURL("https://www.google.com/");
4463 request.load_flags = 0;
4464
4465 MockWrite proxy_writes[] = {
4466 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454467 "Host: www.google.com\r\n"
4468 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334469 };
4470
4471 MockRead proxy_reads[] = {
4472 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424473 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334474 };
4475
4476 MockWrite data_writes[] = {
4477 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454478 "Host: www.google.com\r\n"
4479 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334480 MockWrite("GET / HTTP/1.1\r\n"
4481 "Host: www.google.com\r\n"
4482 "Connection: keep-alive\r\n\r\n"),
4483 };
4484
4485 MockRead data_reads[] = {
4486 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4487 MockRead("HTTP/1.0 200 OK\r\n"),
4488 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4489 MockRead("Content-Length: 100\r\n\r\n"),
4490 MockRead(false, OK),
4491 };
4492
[email protected]31a2bfe2010-02-09 08:03:394493 StaticSocketDataProvider ssl_bad_certificate(
4494 proxy_reads, arraysize(proxy_reads),
4495 proxy_writes, arraysize(proxy_writes));
4496 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4497 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594498 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4499 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334500
[email protected]5ecc992a42009-11-11 01:41:594501 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4502 session_deps.socket_factory.AddSocketDataProvider(&data);
4503 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4504 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334505
[email protected]f1f3f0f82011-10-01 20:38:104506 TestOldCompletionCallback callback;
[email protected]bacff652009-03-31 17:50:334507
4508 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594509 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334510
[email protected]d207a5f2009-06-04 05:28:404511 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434512 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334513
[email protected]5a1d7ca2010-04-28 20:12:274514 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334515 EXPECT_EQ(ERR_IO_PENDING, rv);
4516
4517 rv = callback.WaitForResult();
4518 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4519
4520 rv = trans->RestartIgnoringLastError(&callback);
4521 EXPECT_EQ(ERR_IO_PENDING, rv);
4522
4523 rv = callback.WaitForResult();
4524 EXPECT_EQ(OK, rv);
4525
4526 const HttpResponseInfo* response = trans->GetResponseInfo();
4527
[email protected]fe2255a2011-09-20 19:37:504528 ASSERT_TRUE(response != NULL);
[email protected]bacff652009-03-31 17:50:334529 EXPECT_EQ(100, response->headers->GetContentLength());
4530 }
4531}
4532
[email protected]2df19bb2010-08-25 20:13:464533
4534// Test HTTPS connections to a site, going through an HTTPS proxy
4535TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114536 SessionDependencies session_deps(ProxyService::CreateFixed(
4537 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464538
4539 HttpRequestInfo request;
4540 request.method = "GET";
4541 request.url = GURL("https://www.google.com/");
4542 request.load_flags = 0;
4543
4544 MockWrite data_writes[] = {
4545 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4546 "Host: www.google.com\r\n"
4547 "Proxy-Connection: keep-alive\r\n\r\n"),
4548 MockWrite("GET / HTTP/1.1\r\n"
4549 "Host: www.google.com\r\n"
4550 "Connection: keep-alive\r\n\r\n"),
4551 };
4552
4553 MockRead data_reads[] = {
4554 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4555 MockRead("HTTP/1.1 200 OK\r\n"),
4556 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4557 MockRead("Content-Length: 100\r\n\r\n"),
4558 MockRead(false, OK),
4559 };
4560
4561 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4562 data_writes, arraysize(data_writes));
4563 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4564 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4565
4566 session_deps.socket_factory.AddSocketDataProvider(&data);
4567 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4568 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4569
[email protected]f1f3f0f82011-10-01 20:38:104570 TestOldCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464571
4572 scoped_ptr<HttpTransaction> trans(
4573 new HttpNetworkTransaction(CreateSession(&session_deps)));
4574
4575 int rv = trans->Start(&request, &callback, BoundNetLog());
4576 EXPECT_EQ(ERR_IO_PENDING, rv);
4577
4578 rv = callback.WaitForResult();
4579 EXPECT_EQ(OK, rv);
4580 const HttpResponseInfo* response = trans->GetResponseInfo();
4581
[email protected]fe2255a2011-09-20 19:37:504582 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464583
4584 EXPECT_TRUE(response->headers->IsKeepAlive());
4585 EXPECT_EQ(200, response->headers->response_code());
4586 EXPECT_EQ(100, response->headers->GetContentLength());
4587 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4588}
4589
[email protected]511f6f52010-12-17 03:58:294590// Test an HTTPS Proxy's ability to redirect a CONNECT request
4591TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4592 SessionDependencies session_deps(
4593 ProxyService::CreateFixed("https://proxy:70"));
4594
4595 HttpRequestInfo request;
4596 request.method = "GET";
4597 request.url = GURL("https://www.google.com/");
4598 request.load_flags = 0;
4599
4600 MockWrite data_writes[] = {
4601 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4602 "Host: www.google.com\r\n"
4603 "Proxy-Connection: keep-alive\r\n\r\n"),
4604 };
4605
4606 MockRead data_reads[] = {
4607 MockRead("HTTP/1.1 302 Redirect\r\n"),
4608 MockRead("Location: http://login.example.com/\r\n"),
4609 MockRead("Content-Length: 0\r\n\r\n"),
4610 MockRead(false, OK),
4611 };
4612
4613 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4614 data_writes, arraysize(data_writes));
4615 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4616
4617 session_deps.socket_factory.AddSocketDataProvider(&data);
4618 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4619
[email protected]f1f3f0f82011-10-01 20:38:104620 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294621
4622 scoped_ptr<HttpTransaction> trans(
4623 new HttpNetworkTransaction(CreateSession(&session_deps)));
4624
4625 int rv = trans->Start(&request, &callback, BoundNetLog());
4626 EXPECT_EQ(ERR_IO_PENDING, rv);
4627
4628 rv = callback.WaitForResult();
4629 EXPECT_EQ(OK, rv);
4630 const HttpResponseInfo* response = trans->GetResponseInfo();
4631
[email protected]fe2255a2011-09-20 19:37:504632 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294633
4634 EXPECT_EQ(302, response->headers->response_code());
4635 std::string url;
4636 EXPECT_TRUE(response->headers->IsRedirect(&url));
4637 EXPECT_EQ("http://login.example.com/", url);
4638}
4639
4640// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4641TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4642 SessionDependencies session_deps(
4643 ProxyService::CreateFixed("https://proxy:70"));
4644
4645 HttpRequestInfo request;
4646 request.method = "GET";
4647 request.url = GURL("https://www.google.com/");
4648 request.load_flags = 0;
4649
4650 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4651 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4652 MockWrite data_writes[] = {
4653 CreateMockWrite(*conn.get(), 0, false),
4654 };
4655
4656 static const char* const kExtraHeaders[] = {
4657 "location",
4658 "http://login.example.com/",
4659 };
4660 scoped_ptr<spdy::SpdyFrame> resp(
4661 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4662 arraysize(kExtraHeaders)/2, 1));
4663 MockRead data_reads[] = {
4664 CreateMockRead(*resp.get(), 1, false),
4665 MockRead(true, 0, 2), // EOF
4666 };
4667
4668 scoped_refptr<DelayedSocketData> data(
4669 new DelayedSocketData(
4670 1, // wait for one write to finish before reading.
4671 data_reads, arraysize(data_reads),
4672 data_writes, arraysize(data_writes)));
4673 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4674 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4675 proxy_ssl.next_proto = "spdy/2";
4676 proxy_ssl.was_npn_negotiated = true;
4677
4678 session_deps.socket_factory.AddSocketDataProvider(data.get());
4679 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4680
[email protected]f1f3f0f82011-10-01 20:38:104681 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294682
4683 scoped_ptr<HttpTransaction> trans(
4684 new HttpNetworkTransaction(CreateSession(&session_deps)));
4685
4686 int rv = trans->Start(&request, &callback, BoundNetLog());
4687 EXPECT_EQ(ERR_IO_PENDING, rv);
4688
4689 rv = callback.WaitForResult();
4690 EXPECT_EQ(OK, rv);
4691 const HttpResponseInfo* response = trans->GetResponseInfo();
4692
[email protected]fe2255a2011-09-20 19:37:504693 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294694
4695 EXPECT_EQ(302, response->headers->response_code());
4696 std::string url;
4697 EXPECT_TRUE(response->headers->IsRedirect(&url));
4698 EXPECT_EQ("http://login.example.com/", url);
4699}
4700
4701// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4702TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4703 SessionDependencies session_deps(
4704 ProxyService::CreateFixed("https://proxy:70"));
4705
4706 HttpRequestInfo request;
4707 request.method = "GET";
4708 request.url = GURL("https://www.google.com/");
4709 request.load_flags = 0;
4710
4711 MockWrite data_writes[] = {
4712 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4713 "Host: www.google.com\r\n"
4714 "Proxy-Connection: keep-alive\r\n\r\n"),
4715 };
4716
4717 MockRead data_reads[] = {
4718 MockRead("HTTP/1.1 404 Not Found\r\n"),
4719 MockRead("Content-Length: 23\r\n\r\n"),
4720 MockRead("The host does not exist"),
4721 MockRead(false, OK),
4722 };
4723
4724 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4725 data_writes, arraysize(data_writes));
4726 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4727
4728 session_deps.socket_factory.AddSocketDataProvider(&data);
4729 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4730
[email protected]f1f3f0f82011-10-01 20:38:104731 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294732
4733 scoped_ptr<HttpTransaction> trans(
4734 new HttpNetworkTransaction(CreateSession(&session_deps)));
4735
4736 int rv = trans->Start(&request, &callback, BoundNetLog());
4737 EXPECT_EQ(ERR_IO_PENDING, rv);
4738
4739 rv = callback.WaitForResult();
4740 EXPECT_EQ(OK, rv);
4741 const HttpResponseInfo* response = trans->GetResponseInfo();
4742
[email protected]fe2255a2011-09-20 19:37:504743 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294744
4745 EXPECT_EQ(404, response->headers->response_code());
4746 EXPECT_EQ(23, response->headers->GetContentLength());
4747 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4748 EXPECT_FALSE(response->ssl_info.is_valid());
4749
4750 std::string response_data;
4751 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4752 EXPECT_EQ("The host does not exist", response_data);
4753}
4754
4755// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4756// request
4757TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4758 SessionDependencies session_deps(
4759 ProxyService::CreateFixed("https://proxy:70"));
4760
4761 HttpRequestInfo request;
4762 request.method = "GET";
4763 request.url = GURL("https://www.google.com/");
4764 request.load_flags = 0;
4765
4766 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4767 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4768 MockWrite data_writes[] = {
4769 CreateMockWrite(*conn.get(), 0, false),
4770 };
4771
4772 static const char* const kExtraHeaders[] = {
4773 "location",
4774 "http://login.example.com/",
4775 };
4776 scoped_ptr<spdy::SpdyFrame> resp(
4777 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4778 arraysize(kExtraHeaders)/2, 1));
4779 scoped_ptr<spdy::SpdyFrame> body(
4780 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4781 MockRead data_reads[] = {
4782 CreateMockRead(*resp.get(), 1, false),
4783 CreateMockRead(*body.get(), 2, false),
4784 MockRead(true, 0, 3), // EOF
4785 };
4786
4787 scoped_refptr<DelayedSocketData> data(
4788 new DelayedSocketData(
4789 1, // wait for one write to finish before reading.
4790 data_reads, arraysize(data_reads),
4791 data_writes, arraysize(data_writes)));
4792 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4793 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4794 proxy_ssl.next_proto = "spdy/2";
4795 proxy_ssl.was_npn_negotiated = true;
4796
4797 session_deps.socket_factory.AddSocketDataProvider(data.get());
4798 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4799
[email protected]f1f3f0f82011-10-01 20:38:104800 TestOldCompletionCallback callback;
[email protected]511f6f52010-12-17 03:58:294801
4802 scoped_ptr<HttpTransaction> trans(
4803 new HttpNetworkTransaction(CreateSession(&session_deps)));
4804
4805 int rv = trans->Start(&request, &callback, BoundNetLog());
4806 EXPECT_EQ(ERR_IO_PENDING, rv);
4807
4808 rv = callback.WaitForResult();
4809 EXPECT_EQ(OK, rv);
4810 const HttpResponseInfo* response = trans->GetResponseInfo();
4811
[email protected]fe2255a2011-09-20 19:37:504812 ASSERT_TRUE(response != NULL);
[email protected]511f6f52010-12-17 03:58:294813
4814 EXPECT_EQ(404, response->headers->response_code());
4815 EXPECT_FALSE(response->ssl_info.is_valid());
4816
4817 std::string response_data;
4818 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4819 EXPECT_EQ("The host does not exist", response_data);
4820}
4821
[email protected]2df19bb2010-08-25 20:13:464822// Test HTTPS connections to a site with a bad certificate, going through an
4823// HTTPS proxy
4824TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]3912662a32011-10-04 00:51:114825 SessionDependencies session_deps(ProxyService::CreateFixed(
4826 "https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464827
4828 HttpRequestInfo request;
4829 request.method = "GET";
4830 request.url = GURL("https://www.google.com/");
4831 request.load_flags = 0;
4832
4833 // Attempt to fetch the URL from a server with a bad cert
4834 MockWrite bad_cert_writes[] = {
4835 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4836 "Host: www.google.com\r\n"
4837 "Proxy-Connection: keep-alive\r\n\r\n"),
4838 };
4839
4840 MockRead bad_cert_reads[] = {
4841 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4842 MockRead(false, OK)
4843 };
4844
4845 // Attempt to fetch the URL with a good cert
4846 MockWrite good_data_writes[] = {
4847 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4848 "Host: www.google.com\r\n"
4849 "Proxy-Connection: keep-alive\r\n\r\n"),
4850 MockWrite("GET / HTTP/1.1\r\n"
4851 "Host: www.google.com\r\n"
4852 "Connection: keep-alive\r\n\r\n"),
4853 };
4854
4855 MockRead good_cert_reads[] = {
4856 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4857 MockRead("HTTP/1.0 200 OK\r\n"),
4858 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4859 MockRead("Content-Length: 100\r\n\r\n"),
4860 MockRead(false, OK),
4861 };
4862
4863 StaticSocketDataProvider ssl_bad_certificate(
4864 bad_cert_reads, arraysize(bad_cert_reads),
4865 bad_cert_writes, arraysize(bad_cert_writes));
4866 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4867 good_data_writes, arraysize(good_data_writes));
4868 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4869 SSLSocketDataProvider ssl(true, OK);
4870
4871 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4872 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4873 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4874 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4875
4876 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4877 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4878 session_deps.socket_factory.AddSocketDataProvider(&data);
4879 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4880
[email protected]f1f3f0f82011-10-01 20:38:104881 TestOldCompletionCallback callback;
[email protected]2df19bb2010-08-25 20:13:464882
4883 scoped_ptr<HttpTransaction> trans(
4884 new HttpNetworkTransaction(CreateSession(&session_deps)));
4885
4886 int rv = trans->Start(&request, &callback, BoundNetLog());
4887 EXPECT_EQ(ERR_IO_PENDING, rv);
4888
4889 rv = callback.WaitForResult();
4890 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4891
4892 rv = trans->RestartIgnoringLastError(&callback);
4893 EXPECT_EQ(ERR_IO_PENDING, rv);
4894
4895 rv = callback.WaitForResult();
4896 EXPECT_EQ(OK, rv);
4897
4898 const HttpResponseInfo* response = trans->GetResponseInfo();
4899
[email protected]fe2255a2011-09-20 19:37:504900 ASSERT_TRUE(response != NULL);
[email protected]2df19bb2010-08-25 20:13:464901 EXPECT_EQ(100, response->headers->GetContentLength());
4902}
4903
[email protected]1c773ea12009-04-28 19:58:424904TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424905 HttpRequestInfo request;
4906 request.method = "GET";
4907 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434908 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4909 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424910
[email protected]cb9bf6ca2011-01-28 13:15:274911 SessionDependencies session_deps;
4912 scoped_ptr<HttpTransaction> trans(
4913 new HttpNetworkTransaction(CreateSession(&session_deps)));
4914
[email protected]1c773ea12009-04-28 19:58:424915 MockWrite data_writes[] = {
4916 MockWrite("GET / HTTP/1.1\r\n"
4917 "Host: www.google.com\r\n"
4918 "Connection: keep-alive\r\n"
4919 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4920 };
4921
4922 // Lastly, the server responds with the actual content.
4923 MockRead data_reads[] = {
4924 MockRead("HTTP/1.0 200 OK\r\n"),
4925 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4926 MockRead("Content-Length: 100\r\n\r\n"),
4927 MockRead(false, OK),
4928 };
4929
[email protected]31a2bfe2010-02-09 08:03:394930 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4931 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594932 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424933
[email protected]f1f3f0f82011-10-01 20:38:104934 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:424935
[email protected]5a1d7ca2010-04-28 20:12:274936 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424937 EXPECT_EQ(ERR_IO_PENDING, rv);
4938
4939 rv = callback.WaitForResult();
4940 EXPECT_EQ(OK, rv);
4941}
4942
[email protected]da81f132010-08-18 23:39:294943TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294944 HttpRequestInfo request;
4945 request.method = "GET";
4946 request.url = GURL("https://www.google.com/");
4947 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4948 "Chromium Ultra Awesome X Edition");
4949
[email protected]cb9bf6ca2011-01-28 13:15:274950 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4951 scoped_ptr<HttpTransaction> trans(
4952 new HttpNetworkTransaction(CreateSession(&session_deps)));
4953
[email protected]da81f132010-08-18 23:39:294954 MockWrite data_writes[] = {
4955 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4956 "Host: www.google.com\r\n"
4957 "Proxy-Connection: keep-alive\r\n"
4958 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4959 };
4960 MockRead data_reads[] = {
4961 // Return an error, so the transaction stops here (this test isn't
4962 // interested in the rest).
4963 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4964 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4965 MockRead("Proxy-Connection: close\r\n\r\n"),
4966 };
4967
4968 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4969 data_writes, arraysize(data_writes));
4970 session_deps.socket_factory.AddSocketDataProvider(&data);
4971
[email protected]f1f3f0f82011-10-01 20:38:104972 TestOldCompletionCallback callback;
[email protected]da81f132010-08-18 23:39:294973
4974 int rv = trans->Start(&request, &callback, BoundNetLog());
4975 EXPECT_EQ(ERR_IO_PENDING, rv);
4976
4977 rv = callback.WaitForResult();
4978 EXPECT_EQ(OK, rv);
4979}
4980
[email protected]1c773ea12009-04-28 19:58:424981TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424982 HttpRequestInfo request;
4983 request.method = "GET";
4984 request.url = GURL("http://www.google.com/");
4985 request.load_flags = 0;
[email protected]c10450102011-06-27 09:06:164986 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
4987 "http://the.previous.site.com/");
[email protected]1c773ea12009-04-28 19:58:424988
[email protected]cb9bf6ca2011-01-28 13:15:274989 SessionDependencies session_deps;
4990 scoped_ptr<HttpTransaction> trans(
4991 new HttpNetworkTransaction(CreateSession(&session_deps)));
4992
[email protected]1c773ea12009-04-28 19:58:424993 MockWrite data_writes[] = {
4994 MockWrite("GET / HTTP/1.1\r\n"
4995 "Host: www.google.com\r\n"
4996 "Connection: keep-alive\r\n"
4997 "Referer: http://the.previous.site.com/\r\n\r\n"),
4998 };
4999
5000 // Lastly, the server responds with the actual content.
5001 MockRead data_reads[] = {
5002 MockRead("HTTP/1.0 200 OK\r\n"),
5003 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5004 MockRead("Content-Length: 100\r\n\r\n"),
5005 MockRead(false, OK),
5006 };
5007
[email protected]31a2bfe2010-02-09 08:03:395008 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5009 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595010 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425011
[email protected]f1f3f0f82011-10-01 20:38:105012 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425013
[email protected]5a1d7ca2010-04-28 20:12:275014 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425015 EXPECT_EQ(ERR_IO_PENDING, rv);
5016
5017 rv = callback.WaitForResult();
5018 EXPECT_EQ(OK, rv);
5019}
5020
5021TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425022 HttpRequestInfo request;
5023 request.method = "POST";
5024 request.url = GURL("http://www.google.com/");
5025
[email protected]cb9bf6ca2011-01-28 13:15:275026 SessionDependencies session_deps;
5027 scoped_ptr<HttpTransaction> trans(
5028 new HttpNetworkTransaction(CreateSession(&session_deps)));
5029
[email protected]1c773ea12009-04-28 19:58:425030 MockWrite data_writes[] = {
5031 MockWrite("POST / HTTP/1.1\r\n"
5032 "Host: www.google.com\r\n"
5033 "Connection: keep-alive\r\n"
5034 "Content-Length: 0\r\n\r\n"),
5035 };
5036
5037 // Lastly, the server responds with the actual content.
5038 MockRead data_reads[] = {
5039 MockRead("HTTP/1.0 200 OK\r\n"),
5040 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5041 MockRead("Content-Length: 100\r\n\r\n"),
5042 MockRead(false, OK),
5043 };
5044
[email protected]31a2bfe2010-02-09 08:03:395045 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5046 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595047 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425048
[email protected]f1f3f0f82011-10-01 20:38:105049 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425050
[email protected]5a1d7ca2010-04-28 20:12:275051 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425052 EXPECT_EQ(ERR_IO_PENDING, rv);
5053
5054 rv = callback.WaitForResult();
5055 EXPECT_EQ(OK, rv);
5056}
5057
5058TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425059 HttpRequestInfo request;
5060 request.method = "PUT";
5061 request.url = GURL("http://www.google.com/");
5062
[email protected]cb9bf6ca2011-01-28 13:15:275063 SessionDependencies session_deps;
5064 scoped_ptr<HttpTransaction> trans(
5065 new HttpNetworkTransaction(CreateSession(&session_deps)));
5066
[email protected]1c773ea12009-04-28 19:58:425067 MockWrite data_writes[] = {
5068 MockWrite("PUT / HTTP/1.1\r\n"
5069 "Host: www.google.com\r\n"
5070 "Connection: keep-alive\r\n"
5071 "Content-Length: 0\r\n\r\n"),
5072 };
5073
5074 // Lastly, the server responds with the actual content.
5075 MockRead data_reads[] = {
5076 MockRead("HTTP/1.0 200 OK\r\n"),
5077 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5078 MockRead("Content-Length: 100\r\n\r\n"),
5079 MockRead(false, OK),
5080 };
5081
[email protected]31a2bfe2010-02-09 08:03:395082 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5083 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595084 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425085
[email protected]f1f3f0f82011-10-01 20:38:105086 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425087
[email protected]5a1d7ca2010-04-28 20:12:275088 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425089 EXPECT_EQ(ERR_IO_PENDING, rv);
5090
5091 rv = callback.WaitForResult();
5092 EXPECT_EQ(OK, rv);
5093}
5094
5095TEST_F(HttpNetworkTransactionTest, BuildRequest_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425096 HttpRequestInfo request;
5097 request.method = "HEAD";
5098 request.url = GURL("http://www.google.com/");
5099
[email protected]cb9bf6ca2011-01-28 13:15:275100 SessionDependencies session_deps;
5101 scoped_ptr<HttpTransaction> trans(
5102 new HttpNetworkTransaction(CreateSession(&session_deps)));
5103
[email protected]1c773ea12009-04-28 19:58:425104 MockWrite data_writes[] = {
5105 MockWrite("HEAD / HTTP/1.1\r\n"
5106 "Host: www.google.com\r\n"
5107 "Connection: keep-alive\r\n"
5108 "Content-Length: 0\r\n\r\n"),
5109 };
5110
5111 // Lastly, the server responds with the actual content.
5112 MockRead data_reads[] = {
5113 MockRead("HTTP/1.0 200 OK\r\n"),
5114 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5115 MockRead("Content-Length: 100\r\n\r\n"),
5116 MockRead(false, OK),
5117 };
5118
[email protected]31a2bfe2010-02-09 08:03:395119 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5120 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595121 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425122
[email protected]f1f3f0f82011-10-01 20:38:105123 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425124
[email protected]5a1d7ca2010-04-28 20:12:275125 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425126 EXPECT_EQ(ERR_IO_PENDING, rv);
5127
5128 rv = callback.WaitForResult();
5129 EXPECT_EQ(OK, rv);
5130}
5131
5132TEST_F(HttpNetworkTransactionTest, BuildRequest_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425133 HttpRequestInfo request;
5134 request.method = "GET";
5135 request.url = GURL("http://www.google.com/");
5136 request.load_flags = LOAD_BYPASS_CACHE;
5137
[email protected]cb9bf6ca2011-01-28 13:15:275138 SessionDependencies session_deps;
5139 scoped_ptr<HttpTransaction> trans(
5140 new HttpNetworkTransaction(CreateSession(&session_deps)));
5141
[email protected]1c773ea12009-04-28 19:58:425142 MockWrite data_writes[] = {
5143 MockWrite("GET / HTTP/1.1\r\n"
5144 "Host: www.google.com\r\n"
5145 "Connection: keep-alive\r\n"
5146 "Pragma: no-cache\r\n"
5147 "Cache-Control: no-cache\r\n\r\n"),
5148 };
5149
5150 // Lastly, the server responds with the actual content.
5151 MockRead data_reads[] = {
5152 MockRead("HTTP/1.0 200 OK\r\n"),
5153 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5154 MockRead("Content-Length: 100\r\n\r\n"),
5155 MockRead(false, OK),
5156 };
5157
[email protected]31a2bfe2010-02-09 08:03:395158 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5159 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595160 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425161
[email protected]f1f3f0f82011-10-01 20:38:105162 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425163
[email protected]5a1d7ca2010-04-28 20:12:275164 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425165 EXPECT_EQ(ERR_IO_PENDING, rv);
5166
5167 rv = callback.WaitForResult();
5168 EXPECT_EQ(OK, rv);
5169}
5170
5171TEST_F(HttpNetworkTransactionTest,
5172 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425173 HttpRequestInfo request;
5174 request.method = "GET";
5175 request.url = GURL("http://www.google.com/");
5176 request.load_flags = LOAD_VALIDATE_CACHE;
5177
[email protected]cb9bf6ca2011-01-28 13:15:275178 SessionDependencies session_deps;
5179 scoped_ptr<HttpTransaction> trans(
5180 new HttpNetworkTransaction(CreateSession(&session_deps)));
5181
[email protected]1c773ea12009-04-28 19:58:425182 MockWrite data_writes[] = {
5183 MockWrite("GET / HTTP/1.1\r\n"
5184 "Host: www.google.com\r\n"
5185 "Connection: keep-alive\r\n"
5186 "Cache-Control: max-age=0\r\n\r\n"),
5187 };
5188
5189 // Lastly, the server responds with the actual content.
5190 MockRead data_reads[] = {
5191 MockRead("HTTP/1.0 200 OK\r\n"),
5192 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5193 MockRead("Content-Length: 100\r\n\r\n"),
5194 MockRead(false, OK),
5195 };
5196
[email protected]31a2bfe2010-02-09 08:03:395197 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5198 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595199 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425200
[email protected]f1f3f0f82011-10-01 20:38:105201 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425202
[email protected]5a1d7ca2010-04-28 20:12:275203 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425204 EXPECT_EQ(ERR_IO_PENDING, rv);
5205
5206 rv = callback.WaitForResult();
5207 EXPECT_EQ(OK, rv);
5208}
5209
5210TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425211 HttpRequestInfo request;
5212 request.method = "GET";
5213 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435214 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425215
[email protected]cb9bf6ca2011-01-28 13:15:275216 SessionDependencies session_deps;
5217 scoped_ptr<HttpTransaction> trans(
5218 new HttpNetworkTransaction(CreateSession(&session_deps)));
5219
[email protected]1c773ea12009-04-28 19:58:425220 MockWrite data_writes[] = {
5221 MockWrite("GET / HTTP/1.1\r\n"
5222 "Host: www.google.com\r\n"
5223 "Connection: keep-alive\r\n"
5224 "FooHeader: Bar\r\n\r\n"),
5225 };
5226
5227 // Lastly, the server responds with the actual content.
5228 MockRead data_reads[] = {
5229 MockRead("HTTP/1.0 200 OK\r\n"),
5230 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5231 MockRead("Content-Length: 100\r\n\r\n"),
5232 MockRead(false, OK),
5233 };
5234
[email protected]31a2bfe2010-02-09 08:03:395235 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5236 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595237 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425238
[email protected]f1f3f0f82011-10-01 20:38:105239 TestOldCompletionCallback callback;
[email protected]1c773ea12009-04-28 19:58:425240
[email protected]5a1d7ca2010-04-28 20:12:275241 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425242 EXPECT_EQ(ERR_IO_PENDING, rv);
5243
5244 rv = callback.WaitForResult();
5245 EXPECT_EQ(OK, rv);
5246}
5247
[email protected]270c6412010-03-29 22:02:475248TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475249 HttpRequestInfo request;
5250 request.method = "GET";
5251 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435252 request.extra_headers.SetHeader("referer", "www.foo.com");
5253 request.extra_headers.SetHeader("hEllo", "Kitty");
5254 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475255
[email protected]cb9bf6ca2011-01-28 13:15:275256 SessionDependencies session_deps;
5257 scoped_ptr<HttpTransaction> trans(
5258 new HttpNetworkTransaction(CreateSession(&session_deps)));
5259
[email protected]270c6412010-03-29 22:02:475260 MockWrite data_writes[] = {
5261 MockWrite("GET / HTTP/1.1\r\n"
5262 "Host: www.google.com\r\n"
5263 "Connection: keep-alive\r\n"
[email protected]c10450102011-06-27 09:06:165264 "referer: www.foo.com\r\n"
[email protected]270c6412010-03-29 22:02:475265 "hEllo: Kitty\r\n"
5266 "FoO: bar\r\n\r\n"),
5267 };
5268
5269 // Lastly, the server responds with the actual content.
5270 MockRead data_reads[] = {
5271 MockRead("HTTP/1.0 200 OK\r\n"),
5272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5273 MockRead("Content-Length: 100\r\n\r\n"),
5274 MockRead(false, OK),
5275 };
5276
5277 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5278 data_writes, arraysize(data_writes));
5279 session_deps.socket_factory.AddSocketDataProvider(&data);
5280
[email protected]f1f3f0f82011-10-01 20:38:105281 TestOldCompletionCallback callback;
[email protected]270c6412010-03-29 22:02:475282
[email protected]5a1d7ca2010-04-28 20:12:275283 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475284 EXPECT_EQ(ERR_IO_PENDING, rv);
5285
5286 rv = callback.WaitForResult();
5287 EXPECT_EQ(OK, rv);
5288}
5289
[email protected]3cd17242009-06-23 02:59:025290TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275291 HttpRequestInfo request;
5292 request.method = "GET";
5293 request.url = GURL("http://www.google.com/");
5294 request.load_flags = 0;
5295
[email protected]80d6524d2009-08-18 03:58:095296 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005297 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025298
5299 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435300 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025301
[email protected]3cd17242009-06-23 02:59:025302 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5303 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5304
5305 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355306 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025307 MockWrite("GET / HTTP/1.1\r\n"
5308 "Host: www.google.com\r\n"
5309 "Connection: keep-alive\r\n\r\n")
5310 };
5311
5312 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595313 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025314 MockRead("HTTP/1.0 200 OK\r\n"),
5315 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5316 MockRead("Payload"),
5317 MockRead(false, OK)
5318 };
5319
[email protected]31a2bfe2010-02-09 08:03:395320 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5321 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595322 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025323
[email protected]f1f3f0f82011-10-01 20:38:105324 TestOldCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025325
[email protected]5a1d7ca2010-04-28 20:12:275326 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025327 EXPECT_EQ(ERR_IO_PENDING, rv);
5328
5329 rv = callback.WaitForResult();
5330 EXPECT_EQ(OK, rv);
5331
5332 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505333 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025334
5335 std::string response_text;
5336 rv = ReadTransaction(trans.get(), &response_text);
5337 EXPECT_EQ(OK, rv);
5338 EXPECT_EQ("Payload", response_text);
5339}
5340
5341TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275342 HttpRequestInfo request;
5343 request.method = "GET";
5344 request.url = GURL("https://www.google.com/");
5345 request.load_flags = 0;
5346
[email protected]80d6524d2009-08-18 03:58:095347 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005348 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025349
5350 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435351 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025352
[email protected]3cd17242009-06-23 02:59:025353 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5354 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5355
5356 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355357 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5358 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025359 MockWrite("GET / HTTP/1.1\r\n"
5360 "Host: www.google.com\r\n"
5361 "Connection: keep-alive\r\n\r\n")
5362 };
5363
5364 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355365 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5366 arraysize(read_buffer)),
5367 MockRead("HTTP/1.0 200 OK\r\n"),
5368 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5369 MockRead("Payload"),
5370 MockRead(false, OK)
5371 };
5372
[email protected]31a2bfe2010-02-09 08:03:395373 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5374 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595375 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355376
[email protected]5ecc992a42009-11-11 01:41:595377 SSLSocketDataProvider ssl(true, OK);
5378 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355379
[email protected]f1f3f0f82011-10-01 20:38:105380 TestOldCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355381
[email protected]5a1d7ca2010-04-28 20:12:275382 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355383 EXPECT_EQ(ERR_IO_PENDING, rv);
5384
5385 rv = callback.WaitForResult();
5386 EXPECT_EQ(OK, rv);
5387
5388 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505389 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355390
5391 std::string response_text;
5392 rv = ReadTransaction(trans.get(), &response_text);
5393 EXPECT_EQ(OK, rv);
5394 EXPECT_EQ("Payload", response_text);
5395}
5396
5397TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275398 HttpRequestInfo request;
5399 request.method = "GET";
5400 request.url = GURL("http://www.google.com/");
5401 request.load_flags = 0;
5402
[email protected]80d6524d2009-08-18 03:58:095403 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005404 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355405
5406 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435407 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355408
[email protected]e0c27be2009-07-15 13:09:355409 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5410 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375411 const char kSOCKS5OkRequest[] = {
5412 0x05, // Version
5413 0x01, // Command (CONNECT)
5414 0x00, // Reserved.
5415 0x03, // Address type (DOMAINNAME).
5416 0x0E, // Length of domain (14)
5417 // Domain string:
5418 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5419 0x00, 0x50, // 16-bit port (80)
5420 };
[email protected]e0c27be2009-07-15 13:09:355421 const char kSOCKS5OkResponse[] =
5422 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5423
5424 MockWrite data_writes[] = {
5425 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5426 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5427 MockWrite("GET / HTTP/1.1\r\n"
5428 "Host: www.google.com\r\n"
5429 "Connection: keep-alive\r\n\r\n")
5430 };
5431
5432 MockRead data_reads[] = {
5433 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5434 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5435 MockRead("HTTP/1.0 200 OK\r\n"),
5436 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5437 MockRead("Payload"),
5438 MockRead(false, OK)
5439 };
5440
[email protected]31a2bfe2010-02-09 08:03:395441 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5442 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595443 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355444
[email protected]f1f3f0f82011-10-01 20:38:105445 TestOldCompletionCallback callback;
[email protected]e0c27be2009-07-15 13:09:355446
[email protected]5a1d7ca2010-04-28 20:12:275447 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355448 EXPECT_EQ(ERR_IO_PENDING, rv);
5449
5450 rv = callback.WaitForResult();
5451 EXPECT_EQ(OK, rv);
5452
5453 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505454 ASSERT_TRUE(response != NULL);
[email protected]e0c27be2009-07-15 13:09:355455
5456 std::string response_text;
5457 rv = ReadTransaction(trans.get(), &response_text);
5458 EXPECT_EQ(OK, rv);
5459 EXPECT_EQ("Payload", response_text);
5460}
5461
5462TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275463 HttpRequestInfo request;
5464 request.method = "GET";
5465 request.url = GURL("https://www.google.com/");
5466 request.load_flags = 0;
5467
[email protected]80d6524d2009-08-18 03:58:095468 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005469 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355470
5471 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435472 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355473
[email protected]e0c27be2009-07-15 13:09:355474 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5475 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375476 const unsigned char kSOCKS5OkRequest[] = {
5477 0x05, // Version
5478 0x01, // Command (CONNECT)
5479 0x00, // Reserved.
5480 0x03, // Address type (DOMAINNAME).
5481 0x0E, // Length of domain (14)
5482 // Domain string:
5483 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5484 0x01, 0xBB, // 16-bit port (443)
5485 };
5486
[email protected]e0c27be2009-07-15 13:09:355487 const char kSOCKS5OkResponse[] =
5488 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5489
5490 MockWrite data_writes[] = {
5491 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5492 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5493 arraysize(kSOCKS5OkRequest)),
5494 MockWrite("GET / HTTP/1.1\r\n"
5495 "Host: www.google.com\r\n"
5496 "Connection: keep-alive\r\n\r\n")
5497 };
5498
5499 MockRead data_reads[] = {
5500 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5501 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025502 MockRead("HTTP/1.0 200 OK\r\n"),
5503 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5504 MockRead("Payload"),
5505 MockRead(false, OK)
5506 };
5507
[email protected]31a2bfe2010-02-09 08:03:395508 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5509 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595510 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025511
[email protected]5ecc992a42009-11-11 01:41:595512 SSLSocketDataProvider ssl(true, OK);
5513 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025514
[email protected]f1f3f0f82011-10-01 20:38:105515 TestOldCompletionCallback callback;
[email protected]3cd17242009-06-23 02:59:025516
[email protected]5a1d7ca2010-04-28 20:12:275517 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025518 EXPECT_EQ(ERR_IO_PENDING, rv);
5519
5520 rv = callback.WaitForResult();
5521 EXPECT_EQ(OK, rv);
5522
5523 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505524 ASSERT_TRUE(response != NULL);
[email protected]3cd17242009-06-23 02:59:025525
5526 std::string response_text;
5527 rv = ReadTransaction(trans.get(), &response_text);
5528 EXPECT_EQ(OK, rv);
5529 EXPECT_EQ("Payload", response_text);
5530}
5531
[email protected]04e5be32009-06-26 20:00:315532// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065533
5534struct GroupNameTest {
5535 std::string proxy_server;
5536 std::string url;
5537 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185538 bool ssl;
[email protected]2d731a32010-04-29 01:04:065539};
5540
5541scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025542 SessionDependencies* session_deps) {
5543 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065544
[email protected]17291a022011-10-10 07:32:535545 HttpServerProperties* http_server_properties =
5546 session->http_server_properties();
5547 http_server_properties->SetAlternateProtocol(
[email protected]2d731a32010-04-29 01:04:065548 HostPortPair("host.with.alternate", 80), 443,
[email protected]17291a022011-10-10 07:32:535549 NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065550
5551 return session;
5552}
5553
5554int GroupNameTransactionHelper(
5555 const std::string& url,
5556 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065557 HttpRequestInfo request;
5558 request.method = "GET";
5559 request.url = GURL(url);
5560 request.load_flags = 0;
5561
[email protected]cb9bf6ca2011-01-28 13:15:275562 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5563
[email protected]f1f3f0f82011-10-01 20:38:105564 TestOldCompletionCallback callback;
[email protected]2d731a32010-04-29 01:04:065565
5566 // We do not complete this request, the dtor will clean the transaction up.
5567 return trans->Start(&request, &callback, BoundNetLog());
5568}
5569
5570TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5571 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315572 {
[email protected]2d731a32010-04-29 01:04:065573 "", // unused
[email protected]04e5be32009-06-26 20:00:315574 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545575 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185576 false,
[email protected]2ff8b312010-04-26 22:20:545577 },
5578 {
[email protected]2d731a32010-04-29 01:04:065579 "", // unused
[email protected]2ff8b312010-04-26 22:20:545580 "http://[2001:1418:13:1::25]/direct",
5581 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185582 false,
[email protected]04e5be32009-06-26 20:00:315583 },
[email protected]04e5be32009-06-26 20:00:315584
5585 // SSL Tests
5586 {
[email protected]2d731a32010-04-29 01:04:065587 "", // unused
[email protected]04e5be32009-06-26 20:00:315588 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025589 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185590 true,
[email protected]04e5be32009-06-26 20:00:315591 },
5592 {
[email protected]2d731a32010-04-29 01:04:065593 "", // unused
5594 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025595 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185596 true,
[email protected]04e5be32009-06-26 20:00:315597 },
5598 {
[email protected]2d731a32010-04-29 01:04:065599 "", // unused
[email protected]2ff8b312010-04-26 22:20:545600 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025601 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185602 true,
[email protected]2ff8b312010-04-26 22:20:545603 },
[email protected]2d731a32010-04-29 01:04:065604 };
[email protected]2ff8b312010-04-26 22:20:545605
[email protected]8e6441ca2010-08-19 05:56:385606 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065607
5608 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025609 SessionDependencies session_deps(
5610 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065611 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025612 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065613
5614 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285615 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5616 new CaptureGroupNameTransportSocketPool(NULL, NULL);
5617 peer.SetTransportSocketPool(transport_conn_pool);
[email protected]2431756e2010-09-29 20:26:135618 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345619 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185620 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065621
5622 EXPECT_EQ(ERR_IO_PENDING,
5623 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185624 if (tests[i].ssl)
5625 EXPECT_EQ(tests[i].expected_group_name,
5626 ssl_conn_pool->last_group_name_received());
5627 else
5628 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285629 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065630 }
5631
[email protected]8e6441ca2010-08-19 05:56:385632 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065633}
5634
5635TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5636 const GroupNameTest tests[] = {
5637 {
5638 "http_proxy",
5639 "http://www.google.com/http_proxy_normal",
5640 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185641 false,
[email protected]2d731a32010-04-29 01:04:065642 },
5643
5644 // SSL Tests
5645 {
5646 "http_proxy",
5647 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025648 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185649 true,
[email protected]2d731a32010-04-29 01:04:065650 },
[email protected]af3490e2010-10-16 21:02:295651
[email protected]9faeded92010-04-29 20:03:055652 {
5653 "http_proxy",
5654 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025655 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185656 true,
[email protected]9faeded92010-04-29 20:03:055657 },
[email protected]2d731a32010-04-29 01:04:065658 };
5659
[email protected]8e6441ca2010-08-19 05:56:385660 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065661
5662 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025663 SessionDependencies session_deps(
5664 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065665 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025666 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065667
5668 HttpNetworkSessionPeer peer(session);
5669
[email protected]e60e47a2010-07-14 03:37:185670 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135671 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345672 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185673 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135674 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345675 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185676 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065677
5678 EXPECT_EQ(ERR_IO_PENDING,
5679 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185680 if (tests[i].ssl)
5681 EXPECT_EQ(tests[i].expected_group_name,
5682 ssl_conn_pool->last_group_name_received());
5683 else
5684 EXPECT_EQ(tests[i].expected_group_name,
5685 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065686 }
5687
[email protected]8e6441ca2010-08-19 05:56:385688 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065689}
5690
5691TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5692 const GroupNameTest tests[] = {
5693 {
5694 "socks4://socks_proxy:1080",
5695 "http://www.google.com/socks4_direct",
5696 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185697 false,
[email protected]2d731a32010-04-29 01:04:065698 },
5699 {
5700 "socks5://socks_proxy:1080",
5701 "http://www.google.com/socks5_direct",
5702 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185703 false,
[email protected]2d731a32010-04-29 01:04:065704 },
5705
5706 // SSL Tests
5707 {
5708 "socks4://socks_proxy:1080",
5709 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025710 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185711 true,
[email protected]2d731a32010-04-29 01:04:065712 },
5713 {
5714 "socks5://socks_proxy:1080",
5715 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025716 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185717 true,
[email protected]2d731a32010-04-29 01:04:065718 },
[email protected]af3490e2010-10-16 21:02:295719
[email protected]9faeded92010-04-29 20:03:055720 {
5721 "socks4://socks_proxy:1080",
5722 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025723 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185724 true,
[email protected]9faeded92010-04-29 20:03:055725 },
[email protected]04e5be32009-06-26 20:00:315726 };
5727
[email protected]8e6441ca2010-08-19 05:56:385728 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545729
[email protected]04e5be32009-06-26 20:00:315730 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025731 SessionDependencies session_deps(
5732 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065733 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025734 SetupSessionForGroupNameTests(&session_deps));
5735
[email protected]2d731a32010-04-29 01:04:065736 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315737
[email protected]e60e47a2010-07-14 03:37:185738 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135739 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345740 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185741 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135742 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345743 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185744 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315745
[email protected]5695b8c2009-09-30 21:36:435746 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315747
[email protected]2d731a32010-04-29 01:04:065748 EXPECT_EQ(ERR_IO_PENDING,
5749 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185750 if (tests[i].ssl)
5751 EXPECT_EQ(tests[i].expected_group_name,
5752 ssl_conn_pool->last_group_name_received());
5753 else
5754 EXPECT_EQ(tests[i].expected_group_name,
5755 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315756 }
[email protected]2ff8b312010-04-26 22:20:545757
[email protected]8e6441ca2010-08-19 05:56:385758 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315759}
5760
[email protected]9172a982009-06-06 00:30:255761TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275762 HttpRequestInfo request;
5763 request.method = "GET";
5764 request.url = GURL("http://www.google.com/");
5765
[email protected]5c6a17e2009-06-10 00:54:545766 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005767 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325768
[email protected]69719062010-01-05 20:09:215769 // This simulates failure resolving all hostnames; that means we will fail
5770 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325771 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5772
[email protected]9172a982009-06-06 00:30:255773 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435774 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255775
[email protected]f1f3f0f82011-10-01 20:38:105776 TestOldCompletionCallback callback;
[email protected]9172a982009-06-06 00:30:255777
[email protected]5a1d7ca2010-04-28 20:12:275778 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255779 EXPECT_EQ(ERR_IO_PENDING, rv);
5780
[email protected]9172a982009-06-06 00:30:255781 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015782 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255783}
5784
[email protected]f3e6c1e2009-06-15 20:52:125785// Host resolution observer used by
5786// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5787// resovle requests are issued with a referrer of |expected_referrer|.
5788class ResolutionReferrerObserver : public HostResolver::Observer {
5789 public:
5790 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5791 : expected_referrer_(expected_referrer),
5792 called_start_with_referrer_(false),
5793 called_finish_with_referrer_(false) {
5794 }
5795
5796 virtual void OnStartResolution(int id,
5797 const HostResolver::RequestInfo& info) {
5798 if (info.referrer() == expected_referrer_)
5799 called_start_with_referrer_ = true;
5800 }
5801
5802 virtual void OnFinishResolutionWithStatus(
5803 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5804 if (info.referrer() == expected_referrer_)
5805 called_finish_with_referrer_ = true;
5806 }
5807
[email protected]eb255d32009-06-17 02:11:035808 virtual void OnCancelResolution(int id,
5809 const HostResolver::RequestInfo& info ) {
5810 FAIL() << "Should not be cancelling any requests!";
5811 }
5812
[email protected]f3e6c1e2009-06-15 20:52:125813 bool did_complete_with_expected_referrer() const {
5814 return called_start_with_referrer_ && called_finish_with_referrer_;
5815 }
5816
5817 private:
5818 GURL expected_referrer_;
5819 bool called_start_with_referrer_;
5820 bool called_finish_with_referrer_;
5821
5822 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5823};
5824
5825// Make sure that when HostResolver::Resolve() is invoked, it passes through
5826// the "referrer". This is depended on by the DNS prefetch observer.
5827TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5828 GURL referrer = GURL("http://expected-referrer/");
5829 EXPECT_TRUE(referrer.is_valid());
5830 ResolutionReferrerObserver resolution_observer(referrer);
5831
[email protected]cb9bf6ca2011-01-28 13:15:275832 // Issue a request, containing an HTTP referrer.
5833 HttpRequestInfo request;
5834 request.method = "GET";
[email protected]cb9bf6ca2011-01-28 13:15:275835 request.url = GURL("http://www.google.com/");
[email protected]c10450102011-06-27 09:06:165836 request.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
5837 referrer.spec());
[email protected]cb9bf6ca2011-01-28 13:15:275838
[email protected]f3e6c1e2009-06-15 20:52:125839 SessionDependencies session_deps;
5840 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435841 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125842
5843 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145844 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125845
5846 // Connect up a mock socket which will fail when reading.
5847 MockRead data_reads[] = {
5848 MockRead(false, ERR_FAILED),
5849 };
[email protected]31a2bfe2010-02-09 08:03:395850 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595851 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125852
[email protected]f3e6c1e2009-06-15 20:52:125853 // Run the request until it fails reading from the socket.
[email protected]f1f3f0f82011-10-01 20:38:105854 TestOldCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275855 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125856 EXPECT_EQ(ERR_IO_PENDING, rv);
5857 rv = callback.WaitForResult();
5858 EXPECT_EQ(ERR_FAILED, rv);
5859
5860 // Check that the host resolution observer saw |referrer|.
5861 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5862}
5863
[email protected]685af592010-05-11 19:31:245864// Base test to make sure that when the load flags for a request specify to
5865// bypass the cache, the DNS cache is not used.
5866void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275867 // Issue a request, asking to bypass the cache(s).
5868 HttpRequestInfo request;
5869 request.method = "GET";
5870 request.load_flags = load_flags;
5871 request.url = GURL("http://www.google.com/");
5872
[email protected]3b9cca42009-06-16 01:08:285873 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325874
[email protected]a2c2fb92009-07-18 07:31:045875 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545876 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325877
[email protected]3b9cca42009-06-16 01:08:285878 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435879 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285880
[email protected]6e78dfb2011-07-28 21:34:475881 // Warm up the host cache so it has an entry for "www.google.com".
[email protected]3b9cca42009-06-16 01:08:285882 AddressList addrlist;
[email protected]f1f3f0f82011-10-01 20:38:105883 TestOldCompletionCallback callback;
[email protected]94a0d3d92009-06-27 01:50:145884 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105885 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]6e78dfb2011-07-28 21:34:475886 &callback, NULL, BoundNetLog());
5887 EXPECT_EQ(ERR_IO_PENDING, rv);
5888 rv = callback.WaitForResult();
[email protected]3b9cca42009-06-16 01:08:285889 EXPECT_EQ(OK, rv);
5890
5891 // Verify that it was added to host cache, by doing a subsequent async lookup
5892 // and confirming it completes synchronously.
[email protected]684970b2009-08-14 04:54:465893 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105894 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]6e78dfb2011-07-28 21:34:475895 &callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325896 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285897
5898 // Inject a failure the next time that "www.google.com" is resolved. This way
5899 // we can tell if the next lookup hit the cache, or the "network".
5900 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325901 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285902
5903 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5904 // first read -- this won't be reached as the host resolution will fail first.
5905 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395906 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595907 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285908
[email protected]3b9cca42009-06-16 01:08:285909 // Run the request.
[email protected]5a1d7ca2010-04-28 20:12:275910 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285911 ASSERT_EQ(ERR_IO_PENDING, rv);
5912 rv = callback.WaitForResult();
5913
5914 // If we bypassed the cache, we would have gotten a failure while resolving
5915 // "www.google.com".
5916 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5917}
5918
[email protected]685af592010-05-11 19:31:245919// There are multiple load flags that should trigger the host cache bypass.
5920// Test each in isolation:
5921TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5922 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5923}
5924
5925TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5926 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5927}
5928
5929TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5930 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5931}
5932
[email protected]0877e3d2009-10-17 22:29:575933// Make sure we can handle an error when writing the request.
5934TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5935 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275936 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575937
5938 HttpRequestInfo request;
5939 request.method = "GET";
5940 request.url = GURL("http://www.foo.com/");
5941 request.load_flags = 0;
5942
5943 MockWrite write_failure[] = {
5944 MockWrite(true, ERR_CONNECTION_RESET),
5945 };
[email protected]31a2bfe2010-02-09 08:03:395946 StaticSocketDataProvider data(NULL, 0,
5947 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595948 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575949
[email protected]f1f3f0f82011-10-01 20:38:105950 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575951
5952 scoped_ptr<HttpTransaction> trans(
5953 new HttpNetworkTransaction(CreateSession(&session_deps)));
5954
[email protected]5a1d7ca2010-04-28 20:12:275955 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575956 EXPECT_EQ(ERR_IO_PENDING, rv);
5957
5958 rv = callback.WaitForResult();
5959 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5960}
5961
5962// Check that a connection closed after the start of the headers finishes ok.
5963TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5964 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275965 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575966
5967 HttpRequestInfo request;
5968 request.method = "GET";
5969 request.url = GURL("http://www.foo.com/");
5970 request.load_flags = 0;
5971
5972 MockRead data_reads[] = {
5973 MockRead("HTTP/1."),
5974 MockRead(false, OK),
5975 };
5976
[email protected]31a2bfe2010-02-09 08:03:395977 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595978 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575979
[email protected]f1f3f0f82011-10-01 20:38:105980 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:575981
5982 scoped_ptr<HttpTransaction> trans(
5983 new HttpNetworkTransaction(CreateSession(&session_deps)));
5984
[email protected]5a1d7ca2010-04-28 20:12:275985 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575986 EXPECT_EQ(ERR_IO_PENDING, rv);
5987
5988 rv = callback.WaitForResult();
5989 EXPECT_EQ(OK, rv);
5990
5991 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:505992 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:575993
5994 EXPECT_TRUE(response->headers != NULL);
5995 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5996
5997 std::string response_data;
5998 rv = ReadTransaction(trans.get(), &response_data);
5999 EXPECT_EQ(OK, rv);
6000 EXPECT_EQ("", response_data);
6001}
6002
6003// Make sure that a dropped connection while draining the body for auth
6004// restart does the right thing.
6005TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
6006 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:276007 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:576008
6009 HttpRequestInfo request;
6010 request.method = "GET";
6011 request.url = GURL("http://www.google.com/");
6012 request.load_flags = 0;
6013
6014 MockWrite data_writes1[] = {
6015 MockWrite("GET / HTTP/1.1\r\n"
6016 "Host: www.google.com\r\n"
6017 "Connection: keep-alive\r\n\r\n"),
6018 };
6019
6020 MockRead data_reads1[] = {
6021 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6022 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6023 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6024 MockRead("Content-Length: 14\r\n\r\n"),
6025 MockRead("Unauth"),
6026 MockRead(true, ERR_CONNECTION_RESET),
6027 };
6028
[email protected]31a2bfe2010-02-09 08:03:396029 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6030 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:596031 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:576032
6033 // After calling trans->RestartWithAuth(), this is the request we should
6034 // be issuing -- the final header line contains the credentials.
6035 MockWrite data_writes2[] = {
6036 MockWrite("GET / HTTP/1.1\r\n"
6037 "Host: www.google.com\r\n"
6038 "Connection: keep-alive\r\n"
6039 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6040 };
6041
6042 // Lastly, the server responds with the actual content.
6043 MockRead data_reads2[] = {
6044 MockRead("HTTP/1.1 200 OK\r\n"),
6045 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
6046 MockRead("Content-Length: 100\r\n\r\n"),
6047 MockRead(false, OK),
6048 };
6049
[email protected]31a2bfe2010-02-09 08:03:396050 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6051 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:596052 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:576053
[email protected]f1f3f0f82011-10-01 20:38:106054 TestOldCompletionCallback callback1;
[email protected]0877e3d2009-10-17 22:29:576055
[email protected]0b0bf032010-09-21 18:08:506056 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6057
[email protected]5a1d7ca2010-04-28 20:12:276058 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576059 EXPECT_EQ(ERR_IO_PENDING, rv);
6060
6061 rv = callback1.WaitForResult();
6062 EXPECT_EQ(OK, rv);
6063
6064 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506065 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046066 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]0877e3d2009-10-17 22:29:576067
[email protected]f1f3f0f82011-10-01 20:38:106068 TestOldCompletionCallback callback2;
[email protected]0877e3d2009-10-17 22:29:576069
[email protected]13c8a092010-07-29 06:15:446070 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:576071 EXPECT_EQ(ERR_IO_PENDING, rv);
6072
6073 rv = callback2.WaitForResult();
6074 EXPECT_EQ(OK, rv);
6075
6076 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506077 ASSERT_TRUE(response != NULL);
[email protected]0877e3d2009-10-17 22:29:576078 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6079 EXPECT_EQ(100, response->headers->GetContentLength());
6080}
6081
6082// Test HTTPS connections going through a proxy that sends extra data.
6083TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006084 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576085
6086 HttpRequestInfo request;
6087 request.method = "GET";
6088 request.url = GURL("https://www.google.com/");
6089 request.load_flags = 0;
6090
6091 MockRead proxy_reads[] = {
6092 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6093 MockRead(false, OK)
6094 };
6095
[email protected]31a2bfe2010-02-09 08:03:396096 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596097 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576098
[email protected]5ecc992a42009-11-11 01:41:596099 session_deps.socket_factory.AddSocketDataProvider(&data);
6100 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576101
[email protected]f1f3f0f82011-10-01 20:38:106102 TestOldCompletionCallback callback;
[email protected]0877e3d2009-10-17 22:29:576103
6104 session_deps.socket_factory.ResetNextMockIndexes();
6105
6106 scoped_ptr<HttpTransaction> trans(
6107 new HttpNetworkTransaction(CreateSession(&session_deps)));
6108
[email protected]5a1d7ca2010-04-28 20:12:276109 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576110 EXPECT_EQ(ERR_IO_PENDING, rv);
6111
6112 rv = callback.WaitForResult();
6113 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6114}
6115
[email protected]e22e1362009-11-23 21:31:126116TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466117 HttpRequestInfo request;
6118 request.method = "GET";
6119 request.url = GURL("http://www.google.com/");
6120 request.load_flags = 0;
6121
[email protected]cb9bf6ca2011-01-28 13:15:276122 SessionDependencies session_deps;
6123 scoped_ptr<HttpTransaction> trans(
6124 new HttpNetworkTransaction(CreateSession(&session_deps)));
6125
[email protected]e22e1362009-11-23 21:31:126126 MockRead data_reads[] = {
6127 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6128 MockRead(false, OK),
6129 };
[email protected]9492e4a2010-02-24 00:58:466130
6131 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6132 session_deps.socket_factory.AddSocketDataProvider(&data);
6133
[email protected]f1f3f0f82011-10-01 20:38:106134 TestOldCompletionCallback callback;
[email protected]9492e4a2010-02-24 00:58:466135
[email protected]5a1d7ca2010-04-28 20:12:276136 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466137 EXPECT_EQ(ERR_IO_PENDING, rv);
6138
6139 EXPECT_EQ(OK, callback.WaitForResult());
6140
6141 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506142 ASSERT_TRUE(response != NULL);
[email protected]9492e4a2010-02-24 00:58:466143
6144 EXPECT_TRUE(response->headers != NULL);
6145 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6146
6147 std::string response_data;
6148 rv = ReadTransaction(trans.get(), &response_data);
[email protected]f0e2bf42011-07-22 21:21:446149 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126150}
6151
[email protected]95d88ffe2010-02-04 21:25:336152TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336153 HttpRequestInfo request;
6154 request.method = "POST";
6155 request.url = GURL("http://www.google.com/upload");
6156 request.upload_data = new UploadData;
6157 request.load_flags = 0;
6158
[email protected]cb9bf6ca2011-01-28 13:15:276159 SessionDependencies session_deps;
6160 scoped_ptr<HttpTransaction> trans(
6161 new HttpNetworkTransaction(CreateSession(&session_deps)));
6162
[email protected]95d88ffe2010-02-04 21:25:336163 FilePath temp_file_path;
6164 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6165 const uint64 kFakeSize = 100000; // file is actually blank
6166
6167 std::vector<UploadData::Element> elements;
6168 UploadData::Element element;
6169 element.SetToFilePath(temp_file_path);
6170 element.SetContentLength(kFakeSize);
6171 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536172 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336173 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6174
6175 MockRead data_reads[] = {
6176 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6177 MockRead("hello world"),
6178 MockRead(false, OK),
6179 };
[email protected]31a2bfe2010-02-09 08:03:396180 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336181 session_deps.socket_factory.AddSocketDataProvider(&data);
6182
[email protected]f1f3f0f82011-10-01 20:38:106183 TestOldCompletionCallback callback;
[email protected]95d88ffe2010-02-04 21:25:336184
[email protected]5a1d7ca2010-04-28 20:12:276185 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336186 EXPECT_EQ(ERR_IO_PENDING, rv);
6187
6188 rv = callback.WaitForResult();
6189 EXPECT_EQ(OK, rv);
6190
6191 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506192 ASSERT_TRUE(response != NULL);
[email protected]95d88ffe2010-02-04 21:25:336193
6194 EXPECT_TRUE(response->headers != NULL);
6195 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6196
6197 std::string response_data;
6198 rv = ReadTransaction(trans.get(), &response_data);
6199 EXPECT_EQ(OK, rv);
6200 EXPECT_EQ("hello world", response_data);
6201
6202 file_util::Delete(temp_file_path, false);
6203}
6204
[email protected]6624b4622010-03-29 19:58:366205TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276206 HttpRequestInfo request;
6207 request.method = "POST";
6208 request.url = GURL("http://www.google.com/upload");
6209 request.upload_data = new UploadData;
6210 request.load_flags = 0;
6211
[email protected]6624b4622010-03-29 19:58:366212 // If we try to upload an unreadable file, the network stack should report
6213 // the file size as zero and upload zero bytes for that file.
6214 SessionDependencies session_deps;
6215 scoped_ptr<HttpTransaction> trans(
6216 new HttpNetworkTransaction(CreateSession(&session_deps)));
6217
6218 FilePath temp_file;
6219 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6220 std::string temp_file_content("Unreadable file.");
6221 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6222 temp_file_content.length()));
6223 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6224
[email protected]6624b4622010-03-29 19:58:366225 std::vector<UploadData::Element> elements;
6226 UploadData::Element element;
6227 element.SetToFilePath(temp_file);
6228 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536229 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366230
6231 MockRead data_reads[] = {
6232 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6233 MockRead(false, OK),
6234 };
6235 MockWrite data_writes[] = {
6236 MockWrite("POST /upload HTTP/1.1\r\n"
6237 "Host: www.google.com\r\n"
6238 "Connection: keep-alive\r\n"
6239 "Content-Length: 0\r\n\r\n"),
6240 MockWrite(false, OK),
6241 };
6242 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6243 arraysize(data_writes));
6244 session_deps.socket_factory.AddSocketDataProvider(&data);
6245
[email protected]f1f3f0f82011-10-01 20:38:106246 TestOldCompletionCallback callback;
[email protected]6624b4622010-03-29 19:58:366247
[email protected]5a1d7ca2010-04-28 20:12:276248 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366249 EXPECT_EQ(ERR_IO_PENDING, rv);
6250
6251 rv = callback.WaitForResult();
6252 EXPECT_EQ(OK, rv);
6253
6254 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506255 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366256 EXPECT_TRUE(response->headers != NULL);
6257 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6258
6259 file_util::Delete(temp_file, false);
6260}
6261
6262TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276263 HttpRequestInfo request;
6264 request.method = "POST";
6265 request.url = GURL("http://www.google.com/upload");
6266 request.upload_data = new UploadData;
6267 request.load_flags = 0;
6268
[email protected]6624b4622010-03-29 19:58:366269 SessionDependencies session_deps;
6270 scoped_ptr<HttpTransaction> trans(
6271 new HttpNetworkTransaction(CreateSession(&session_deps)));
6272
6273 FilePath temp_file;
6274 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6275 std::string temp_file_contents("Unreadable file.");
6276 std::string unreadable_contents(temp_file_contents.length(), '\0');
6277 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6278 temp_file_contents.length()));
6279
[email protected]6624b4622010-03-29 19:58:366280 std::vector<UploadData::Element> elements;
6281 UploadData::Element element;
6282 element.SetToFilePath(temp_file);
6283 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536284 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366285
6286 MockRead data_reads[] = {
6287 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6288 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6289 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6290
6291 MockRead("HTTP/1.1 200 OK\r\n"),
6292 MockRead("Content-Length: 0\r\n\r\n"),
6293 MockRead(false, OK),
6294 };
6295 MockWrite data_writes[] = {
6296 MockWrite("POST /upload HTTP/1.1\r\n"
6297 "Host: www.google.com\r\n"
6298 "Connection: keep-alive\r\n"
6299 "Content-Length: 16\r\n\r\n"),
6300 MockWrite(false, temp_file_contents.c_str()),
6301
6302 MockWrite("POST /upload HTTP/1.1\r\n"
6303 "Host: www.google.com\r\n"
6304 "Connection: keep-alive\r\n"
6305 "Content-Length: 16\r\n"
6306 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6307 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6308 MockWrite(false, OK),
6309 };
6310 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6311 arraysize(data_writes));
6312 session_deps.socket_factory.AddSocketDataProvider(&data);
6313
[email protected]f1f3f0f82011-10-01 20:38:106314 TestOldCompletionCallback callback1;
[email protected]6624b4622010-03-29 19:58:366315
[email protected]5a1d7ca2010-04-28 20:12:276316 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366317 EXPECT_EQ(ERR_IO_PENDING, rv);
6318
6319 rv = callback1.WaitForResult();
6320 EXPECT_EQ(OK, rv);
6321
6322 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]79cb5c12011-09-12 13:12:046323 ASSERT_TRUE(response != NULL);
6324 ASSERT_TRUE(response->headers != NULL);
[email protected]6624b4622010-03-29 19:58:366325 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
[email protected]79cb5c12011-09-12 13:12:046326 EXPECT_TRUE(CheckBasicServerAuth(response->auth_challenge.get()));
[email protected]6624b4622010-03-29 19:58:366327
6328 // Now make the file unreadable and try again.
6329 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6330
[email protected]f1f3f0f82011-10-01 20:38:106331 TestOldCompletionCallback callback2;
[email protected]6624b4622010-03-29 19:58:366332
[email protected]13c8a092010-07-29 06:15:446333 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366334 EXPECT_EQ(ERR_IO_PENDING, rv);
6335
6336 rv = callback2.WaitForResult();
6337 EXPECT_EQ(OK, rv);
6338
6339 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506340 ASSERT_TRUE(response != NULL);
[email protected]6624b4622010-03-29 19:58:366341 EXPECT_TRUE(response->headers != NULL);
6342 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6343 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6344
6345 file_util::Delete(temp_file, false);
6346}
6347
[email protected]aeefc9e82010-02-19 16:18:276348// Tests that changes to Auth realms are treated like auth rejections.
6349TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6350 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276351
6352 HttpRequestInfo request;
6353 request.method = "GET";
6354 request.url = GURL("http://www.google.com/");
6355 request.load_flags = 0;
6356
6357 // First transaction will request a resource and receive a Basic challenge
6358 // with realm="first_realm".
6359 MockWrite data_writes1[] = {
6360 MockWrite("GET / HTTP/1.1\r\n"
6361 "Host: www.google.com\r\n"
6362 "Connection: keep-alive\r\n"
6363 "\r\n"),
6364 };
6365 MockRead data_reads1[] = {
6366 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6367 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6368 "\r\n"),
6369 };
6370
6371 // After calling trans->RestartWithAuth(), provide an Authentication header
6372 // for first_realm. The server will reject and provide a challenge with
6373 // second_realm.
6374 MockWrite data_writes2[] = {
6375 MockWrite("GET / HTTP/1.1\r\n"
6376 "Host: www.google.com\r\n"
6377 "Connection: keep-alive\r\n"
6378 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6379 "\r\n"),
6380 };
6381 MockRead data_reads2[] = {
6382 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6383 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6384 "\r\n"),
6385 };
6386
6387 // This again fails, and goes back to first_realm. Make sure that the
6388 // entry is removed from cache.
6389 MockWrite data_writes3[] = {
6390 MockWrite("GET / HTTP/1.1\r\n"
6391 "Host: www.google.com\r\n"
6392 "Connection: keep-alive\r\n"
6393 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6394 "\r\n"),
6395 };
6396 MockRead data_reads3[] = {
6397 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6398 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6399 "\r\n"),
6400 };
6401
6402 // Try one last time (with the correct password) and get the resource.
6403 MockWrite data_writes4[] = {
6404 MockWrite("GET / HTTP/1.1\r\n"
6405 "Host: www.google.com\r\n"
6406 "Connection: keep-alive\r\n"
6407 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6408 "\r\n"),
6409 };
6410 MockRead data_reads4[] = {
6411 MockRead("HTTP/1.1 200 OK\r\n"
6412 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506413 "Content-Length: 5\r\n"
6414 "\r\n"
6415 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276416 };
6417
6418 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6419 data_writes1, arraysize(data_writes1));
6420 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6421 data_writes2, arraysize(data_writes2));
6422 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6423 data_writes3, arraysize(data_writes3));
6424 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6425 data_writes4, arraysize(data_writes4));
6426 session_deps.socket_factory.AddSocketDataProvider(&data1);
6427 session_deps.socket_factory.AddSocketDataProvider(&data2);
6428 session_deps.socket_factory.AddSocketDataProvider(&data3);
6429 session_deps.socket_factory.AddSocketDataProvider(&data4);
6430
[email protected]f1f3f0f82011-10-01 20:38:106431 TestOldCompletionCallback callback1;
[email protected]aeefc9e82010-02-19 16:18:276432
[email protected]0b0bf032010-09-21 18:08:506433 scoped_ptr<HttpTransaction> trans(
6434 new HttpNetworkTransaction(CreateSession(&session_deps)));
6435
[email protected]aeefc9e82010-02-19 16:18:276436 // Issue the first request with Authorize headers. There should be a
6437 // password prompt for first_realm waiting to be filled in after the
6438 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276439 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276440 EXPECT_EQ(ERR_IO_PENDING, rv);
6441 rv = callback1.WaitForResult();
6442 EXPECT_EQ(OK, rv);
6443 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506444 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046445 const AuthChallengeInfo* challenge = response->auth_challenge.get();
6446 ASSERT_FALSE(challenge == NULL);
6447 EXPECT_FALSE(challenge->is_proxy);
6448 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6449 EXPECT_EQ("first_realm", challenge->realm);
6450 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276451
6452 // Issue the second request with an incorrect password. There should be a
6453 // password prompt for second_realm waiting to be filled in after the
6454 // transaction completes.
[email protected]f1f3f0f82011-10-01 20:38:106455 TestOldCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446456 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276457 EXPECT_EQ(ERR_IO_PENDING, rv);
6458 rv = callback2.WaitForResult();
6459 EXPECT_EQ(OK, rv);
6460 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506461 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046462 challenge = response->auth_challenge.get();
6463 ASSERT_FALSE(challenge == NULL);
6464 EXPECT_FALSE(challenge->is_proxy);
6465 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6466 EXPECT_EQ("second_realm", challenge->realm);
6467 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276468
6469 // Issue the third request with another incorrect password. There should be
6470 // a password prompt for first_realm waiting to be filled in. If the password
6471 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6472 // first_realm was not correctly removed.
[email protected]f1f3f0f82011-10-01 20:38:106473 TestOldCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446474 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276475 EXPECT_EQ(ERR_IO_PENDING, rv);
6476 rv = callback3.WaitForResult();
6477 EXPECT_EQ(OK, rv);
6478 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506479 ASSERT_TRUE(response != NULL);
[email protected]79cb5c12011-09-12 13:12:046480 challenge = response->auth_challenge.get();
6481 ASSERT_FALSE(challenge == NULL);
6482 EXPECT_FALSE(challenge->is_proxy);
6483 EXPECT_EQ("www.google.com:80", challenge->challenger.ToString());
6484 EXPECT_EQ("first_realm", challenge->realm);
6485 EXPECT_EQ("basic", challenge->scheme);
[email protected]aeefc9e82010-02-19 16:18:276486
6487 // Issue the fourth request with the correct password and username.
[email protected]f1f3f0f82011-10-01 20:38:106488 TestOldCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446489 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276490 EXPECT_EQ(ERR_IO_PENDING, rv);
6491 rv = callback4.WaitForResult();
6492 EXPECT_EQ(OK, rv);
6493 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:506494 ASSERT_TRUE(response != NULL);
[email protected]aeefc9e82010-02-19 16:18:276495 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6496}
6497
[email protected]564b4912010-03-09 16:30:426498TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]5285d972011-10-18 18:56:346499 HttpStreamFactory::set_next_protos(MakeNextProtos("foo", "bar", NULL));
[email protected]8e6441ca2010-08-19 05:56:386500 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426501
[email protected]564b4912010-03-09 16:30:426502 SessionDependencies session_deps;
6503
6504 MockRead data_reads[] = {
6505 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356506 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426507 MockRead("hello world"),
6508 MockRead(false, OK),
6509 };
6510
6511 HttpRequestInfo request;
6512 request.method = "GET";
6513 request.url = GURL("http://www.google.com/");
6514 request.load_flags = 0;
6515
6516 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6517
6518 session_deps.socket_factory.AddSocketDataProvider(&data);
6519
[email protected]f1f3f0f82011-10-01 20:38:106520 TestOldCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426521
6522 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6523 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6524
[email protected]5a1d7ca2010-04-28 20:12:276525 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426526 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536527
[email protected]2fbaecf22010-07-22 22:20:356528 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]17291a022011-10-10 07:32:536529 const HttpServerProperties& http_server_properties =
6530 *session->http_server_properties();
[email protected]564b4912010-03-09 16:30:426531 EXPECT_FALSE(
[email protected]17291a022011-10-10 07:32:536532 http_server_properties.HasAlternateProtocol(http_host_port_pair));
[email protected]564b4912010-03-09 16:30:426533
6534 EXPECT_EQ(OK, callback.WaitForResult());
6535
6536 const HttpResponseInfo* response = trans->GetResponseInfo();
6537 ASSERT_TRUE(response != NULL);
6538 ASSERT_TRUE(response->headers != NULL);
6539 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536540 EXPECT_FALSE(response->was_fetched_via_spdy);
6541 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426542
6543 std::string response_data;
6544 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6545 EXPECT_EQ("hello world", response_data);
6546
[email protected]17291a022011-10-10 07:32:536547 ASSERT_TRUE(http_server_properties.HasAlternateProtocol(http_host_port_pair));
6548 const PortAlternateProtocolPair alternate =
6549 http_server_properties.GetAlternateProtocol(http_host_port_pair);
6550 PortAlternateProtocolPair expected_alternate;
[email protected]564b4912010-03-09 16:30:426551 expected_alternate.port = 443;
[email protected]17291a022011-10-10 07:32:536552 expected_alternate.protocol = NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426553 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426554
[email protected]8e6441ca2010-08-19 05:56:386555 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]5285d972011-10-18 18:56:346556 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]564b4912010-03-09 16:30:426557}
6558
[email protected]8b95ed62011-03-18 18:12:036559TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386560 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426561 SessionDependencies session_deps;
6562
6563 HttpRequestInfo request;
6564 request.method = "GET";
6565 request.url = GURL("http://www.google.com/");
6566 request.load_flags = 0;
6567
6568 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6569 StaticSocketDataProvider first_data;
6570 first_data.set_connect_data(mock_connect);
6571 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6572
6573 MockRead data_reads[] = {
6574 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6575 MockRead("hello world"),
6576 MockRead(true, OK),
6577 };
6578 StaticSocketDataProvider second_data(
6579 data_reads, arraysize(data_reads), NULL, 0);
6580 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6581
[email protected]564b4912010-03-09 16:30:426582 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6583
[email protected]17291a022011-10-10 07:32:536584 HttpServerProperties* http_server_properties =
6585 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116586 // Port must be < 1024, or the header will be ignored (since initial port was
6587 // port 80 (another restricted port).
[email protected]17291a022011-10-10 07:32:536588 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116589 HostPortPair::FromURL(request.url),
6590 666 /* port is ignored by MockConnect anyway */,
[email protected]17291a022011-10-10 07:32:536591 NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426592
6593 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]3912662a32011-10-04 00:51:116594 TestOldCompletionCallback callback;
[email protected]564b4912010-03-09 16:30:426595
[email protected]5a1d7ca2010-04-28 20:12:276596 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426597 EXPECT_EQ(ERR_IO_PENDING, rv);
6598 EXPECT_EQ(OK, callback.WaitForResult());
6599
6600 const HttpResponseInfo* response = trans->GetResponseInfo();
6601 ASSERT_TRUE(response != NULL);
6602 ASSERT_TRUE(response->headers != NULL);
6603 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6604
6605 std::string response_data;
6606 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6607 EXPECT_EQ("hello world", response_data);
6608
[email protected]17291a022011-10-10 07:32:536609 ASSERT_TRUE(http_server_properties->HasAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116610 HostPortPair::FromURL(request.url)));
[email protected]17291a022011-10-10 07:32:536611 const PortAlternateProtocolPair alternate =
6612 http_server_properties->GetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116613 HostPortPair::FromURL(request.url));
[email protected]17291a022011-10-10 07:32:536614 EXPECT_EQ(ALTERNATE_PROTOCOL_BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386615 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426616}
6617
[email protected]3912662a32011-10-04 00:51:116618TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedBlocked) {
6619 // Ensure that we're not allowed to redirect traffic via an alternate
6620 // protocol to an unrestricted (port >= 1024) when the original traffic was
6621 // on a restricted port (port < 1024). Ensure that we can redirect in all
6622 // other cases.
6623 HttpStreamFactory::set_use_alternate_protocols(true);
6624 SessionDependencies session_deps;
6625
6626 HttpRequestInfo restricted_port_request;
6627 restricted_port_request.method = "GET";
6628 restricted_port_request.url = GURL("http://www.google.com:1023/");
6629 restricted_port_request.load_flags = 0;
6630
6631 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6632 StaticSocketDataProvider first_data;
6633 first_data.set_connect_data(mock_connect);
6634 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6635
6636 MockRead data_reads[] = {
6637 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6638 MockRead("hello world"),
6639 MockRead(true, OK),
6640 };
6641 StaticSocketDataProvider second_data(
6642 data_reads, arraysize(data_reads), NULL, 0);
6643 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6644
6645 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6646
[email protected]17291a022011-10-10 07:32:536647 HttpServerProperties* http_server_properties =
6648 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116649 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536650 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116651 HostPortPair::FromURL(restricted_port_request.url),
6652 kUnrestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536653 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116654
6655 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6656 TestOldCompletionCallback callback;
6657
6658 int rv = trans->Start(&restricted_port_request, &callback, BoundNetLog());
6659 EXPECT_EQ(ERR_IO_PENDING, rv);
6660 // Invalid change to unrestricted port should fail.
6661 EXPECT_EQ(ERR_CONNECTION_REFUSED, callback.WaitForResult());
6662
6663 HttpStreamFactory::set_use_alternate_protocols(false);
6664}
6665
6666TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortRestrictedAllowed) {
6667 // Ensure that we're not allowed to redirect traffic via an alternate
6668 // protocol to an unrestricted (port >= 1024) when the original traffic was
6669 // on a restricted port (port < 1024). Ensure that we can redirect in all
6670 // other cases.
6671 HttpStreamFactory::set_use_alternate_protocols(true);
6672 SessionDependencies session_deps;
6673
6674 HttpRequestInfo restricted_port_request;
6675 restricted_port_request.method = "GET";
6676 restricted_port_request.url = GURL("http://www.google.com:1023/");
6677 restricted_port_request.load_flags = 0;
6678
6679 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6680 StaticSocketDataProvider first_data;
6681 first_data.set_connect_data(mock_connect);
6682 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6683
6684 MockRead data_reads[] = {
6685 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6686 MockRead("hello world"),
6687 MockRead(true, OK),
6688 };
6689 StaticSocketDataProvider second_data(
6690 data_reads, arraysize(data_reads), NULL, 0);
6691 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6692
6693 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6694
[email protected]17291a022011-10-10 07:32:536695 HttpServerProperties* http_server_properties =
6696 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116697 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536698 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116699 HostPortPair::FromURL(restricted_port_request.url),
6700 kRestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536701 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116702
6703 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6704 TestOldCompletionCallback callback;
6705
6706 int rv = trans->Start(&restricted_port_request, &callback, BoundNetLog());
6707 EXPECT_EQ(ERR_IO_PENDING, rv);
6708 // Valid change to restricted port should pass.
6709 EXPECT_EQ(OK, callback.WaitForResult());
6710
6711 HttpStreamFactory::set_use_alternate_protocols(false);
6712}
6713
6714TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed1) {
6715 // Ensure that we're not allowed to redirect traffic via an alternate
6716 // protocol to an unrestricted (port >= 1024) when the original traffic was
6717 // on a restricted port (port < 1024). Ensure that we can redirect in all
6718 // other cases.
6719 HttpStreamFactory::set_use_alternate_protocols(true);
6720 SessionDependencies session_deps;
6721
6722 HttpRequestInfo unrestricted_port_request;
6723 unrestricted_port_request.method = "GET";
6724 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6725 unrestricted_port_request.load_flags = 0;
6726
6727 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6728 StaticSocketDataProvider first_data;
6729 first_data.set_connect_data(mock_connect);
6730 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6731
6732 MockRead data_reads[] = {
6733 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6734 MockRead("hello world"),
6735 MockRead(true, OK),
6736 };
6737 StaticSocketDataProvider second_data(
6738 data_reads, arraysize(data_reads), NULL, 0);
6739 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6740
6741 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6742
[email protected]17291a022011-10-10 07:32:536743 HttpServerProperties* http_server_properties =
6744 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116745 const int kRestrictedAlternatePort = 80;
[email protected]17291a022011-10-10 07:32:536746 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116747 HostPortPair::FromURL(unrestricted_port_request.url),
6748 kRestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536749 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116750
6751 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6752 TestOldCompletionCallback callback;
6753
6754 int rv = trans->Start(&unrestricted_port_request, &callback, BoundNetLog());
6755 EXPECT_EQ(ERR_IO_PENDING, rv);
6756 // Valid change to restricted port should pass.
6757 EXPECT_EQ(OK, callback.WaitForResult());
6758
6759 HttpStreamFactory::set_use_alternate_protocols(false);
6760}
6761
6762TEST_F(HttpNetworkTransactionTest, AlternateProtocolPortUnrestrictedAllowed2) {
6763 // Ensure that we're not allowed to redirect traffic via an alternate
6764 // protocol to an unrestricted (port >= 1024) when the original traffic was
6765 // on a restricted port (port < 1024). Ensure that we can redirect in all
6766 // other cases.
6767 HttpStreamFactory::set_use_alternate_protocols(true);
6768 SessionDependencies session_deps;
6769
6770 HttpRequestInfo unrestricted_port_request;
6771 unrestricted_port_request.method = "GET";
6772 unrestricted_port_request.url = GURL("http://www.google.com:1024/");
6773 unrestricted_port_request.load_flags = 0;
6774
6775 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6776 StaticSocketDataProvider first_data;
6777 first_data.set_connect_data(mock_connect);
6778 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6779
6780 MockRead data_reads[] = {
6781 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6782 MockRead("hello world"),
6783 MockRead(true, OK),
6784 };
6785 StaticSocketDataProvider second_data(
6786 data_reads, arraysize(data_reads), NULL, 0);
6787 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6788
6789 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6790
[email protected]17291a022011-10-10 07:32:536791 HttpServerProperties* http_server_properties =
6792 session->http_server_properties();
[email protected]3912662a32011-10-04 00:51:116793 const int kUnrestrictedAlternatePort = 1024;
[email protected]17291a022011-10-10 07:32:536794 http_server_properties->SetAlternateProtocol(
[email protected]3912662a32011-10-04 00:51:116795 HostPortPair::FromURL(unrestricted_port_request.url),
6796 kUnrestrictedAlternatePort,
[email protected]17291a022011-10-10 07:32:536797 NPN_SPDY_2);
[email protected]3912662a32011-10-04 00:51:116798
6799 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6800 TestOldCompletionCallback callback;
6801
6802 int rv = trans->Start(&unrestricted_port_request, &callback, BoundNetLog());
6803 EXPECT_EQ(ERR_IO_PENDING, rv);
6804 // Valid change to an unrestricted port should pass.
6805 EXPECT_EQ(OK, callback.WaitForResult());
6806
6807 HttpStreamFactory::set_use_alternate_protocols(false);
6808}
6809
[email protected]2ff8b312010-04-26 22:20:546810TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386811 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346812 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:546813 SessionDependencies session_deps;
6814
6815 HttpRequestInfo request;
6816 request.method = "GET";
6817 request.url = GURL("http://www.google.com/");
6818 request.load_flags = 0;
6819
6820 MockRead data_reads[] = {
6821 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356822 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546823 MockRead("hello world"),
6824 MockRead(true, OK),
6825 };
6826
6827 StaticSocketDataProvider first_transaction(
6828 data_reads, arraysize(data_reads), NULL, 0);
6829 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6830
6831 SSLSocketDataProvider ssl(true, OK);
6832 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356833 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536834 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546835 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6836
[email protected]2bd93022010-07-17 00:58:446837 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136838 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546839
[email protected]2bd93022010-07-17 00:58:446840 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6841 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546842 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136843 CreateMockRead(*resp),
6844 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546845 MockRead(true, 0, 0),
6846 };
6847
6848 scoped_refptr<DelayedSocketData> spdy_data(
6849 new DelayedSocketData(
6850 1, // wait for one write to finish before reading.
6851 spdy_reads, arraysize(spdy_reads),
6852 spdy_writes, arraysize(spdy_writes)));
6853 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6854
[email protected]2d6728692011-03-12 01:39:556855 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6856 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6857 NULL, 0, NULL, 0);
6858 hanging_non_alternate_protocol_socket.set_connect_data(
6859 never_finishing_connect);
6860 session_deps.socket_factory.AddSocketDataProvider(
6861 &hanging_non_alternate_protocol_socket);
6862
[email protected]f1f3f0f82011-10-01 20:38:106863 TestOldCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:546864
6865 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6866 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6867
[email protected]5a1d7ca2010-04-28 20:12:276868 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546869 EXPECT_EQ(ERR_IO_PENDING, rv);
6870 EXPECT_EQ(OK, callback.WaitForResult());
6871
6872 const HttpResponseInfo* response = trans->GetResponseInfo();
6873 ASSERT_TRUE(response != NULL);
6874 ASSERT_TRUE(response->headers != NULL);
6875 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6876
6877 std::string response_data;
6878 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6879 EXPECT_EQ("hello world", response_data);
6880
6881 trans.reset(new HttpNetworkTransaction(session));
6882
[email protected]5a1d7ca2010-04-28 20:12:276883 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546884 EXPECT_EQ(ERR_IO_PENDING, rv);
6885 EXPECT_EQ(OK, callback.WaitForResult());
6886
6887 response = trans->GetResponseInfo();
6888 ASSERT_TRUE(response != NULL);
6889 ASSERT_TRUE(response->headers != NULL);
6890 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536891 EXPECT_TRUE(response->was_fetched_via_spdy);
6892 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546893
6894 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6895 EXPECT_EQ("hello!", response_data);
6896
[email protected]5285d972011-10-18 18:56:346897 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:386898 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546899}
6900
[email protected]2d6728692011-03-12 01:39:556901TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6902 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:346903 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:556904 SessionDependencies session_deps;
6905
6906 HttpRequestInfo request;
6907 request.method = "GET";
6908 request.url = GURL("http://www.google.com/");
6909 request.load_flags = 0;
6910
6911 MockRead data_reads[] = {
6912 MockRead("HTTP/1.1 200 OK\r\n"),
6913 MockRead(kAlternateProtocolHttpHeader),
6914 MockRead("hello world"),
6915 MockRead(true, OK),
6916 };
6917
6918 StaticSocketDataProvider first_transaction(
6919 data_reads, arraysize(data_reads), NULL, 0);
6920 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6921 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6922
6923 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6924 StaticSocketDataProvider hanging_socket(
6925 NULL, 0, NULL, 0);
6926 hanging_socket.set_connect_data(never_finishing_connect);
6927 // Socket 2 and 3 are the hanging Alternate-Protocol and
6928 // non-Alternate-Protocol jobs from the 2nd transaction.
6929 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6930 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6931
6932 SSLSocketDataProvider ssl(true, OK);
6933 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6934 ssl.next_proto = "spdy/2";
6935 ssl.was_npn_negotiated = true;
6936 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6937
6938 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6939 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6940 MockWrite spdy_writes[] = {
6941 CreateMockWrite(*req1),
6942 CreateMockWrite(*req2),
6943 };
6944 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6945 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6946 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6947 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6948 MockRead spdy_reads[] = {
6949 CreateMockRead(*resp1),
6950 CreateMockRead(*data1),
6951 CreateMockRead(*resp2),
6952 CreateMockRead(*data2),
6953 MockRead(true, 0, 0),
6954 };
6955
6956 scoped_refptr<DelayedSocketData> spdy_data(
6957 new DelayedSocketData(
6958 2, // wait for writes to finish before reading.
6959 spdy_reads, arraysize(spdy_reads),
6960 spdy_writes, arraysize(spdy_writes)));
6961 // Socket 4 is the successful Alternate-Protocol for transaction 3.
6962 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6963
6964 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6965 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6966
6967 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f1f3f0f82011-10-01 20:38:106968 TestOldCompletionCallback callback1;
[email protected]2d6728692011-03-12 01:39:556969 HttpNetworkTransaction trans1(session);
6970
6971 int rv = trans1.Start(&request, &callback1, BoundNetLog());
6972 EXPECT_EQ(ERR_IO_PENDING, rv);
6973 EXPECT_EQ(OK, callback1.WaitForResult());
6974
6975 const HttpResponseInfo* response = trans1.GetResponseInfo();
6976 ASSERT_TRUE(response != NULL);
6977 ASSERT_TRUE(response->headers != NULL);
6978 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6979
6980 std::string response_data;
6981 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6982 EXPECT_EQ("hello world", response_data);
6983
[email protected]f1f3f0f82011-10-01 20:38:106984 TestOldCompletionCallback callback2;
[email protected]2d6728692011-03-12 01:39:556985 HttpNetworkTransaction trans2(session);
6986 rv = trans2.Start(&request, &callback2, BoundNetLog());
6987 EXPECT_EQ(ERR_IO_PENDING, rv);
6988
[email protected]f1f3f0f82011-10-01 20:38:106989 TestOldCompletionCallback callback3;
[email protected]2d6728692011-03-12 01:39:556990 HttpNetworkTransaction trans3(session);
6991 rv = trans3.Start(&request, &callback3, BoundNetLog());
6992 EXPECT_EQ(ERR_IO_PENDING, rv);
6993
6994 EXPECT_EQ(OK, callback2.WaitForResult());
6995 EXPECT_EQ(OK, callback3.WaitForResult());
6996
6997 response = trans2.GetResponseInfo();
6998 ASSERT_TRUE(response != NULL);
6999 ASSERT_TRUE(response->headers != NULL);
7000 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7001 EXPECT_TRUE(response->was_fetched_via_spdy);
7002 EXPECT_TRUE(response->was_npn_negotiated);
7003 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
7004 EXPECT_EQ("hello!", response_data);
7005
7006 response = trans3.GetResponseInfo();
7007 ASSERT_TRUE(response != NULL);
7008 ASSERT_TRUE(response->headers != NULL);
7009 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7010 EXPECT_TRUE(response->was_fetched_via_spdy);
7011 EXPECT_TRUE(response->was_npn_negotiated);
7012 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
7013 EXPECT_EQ("hello!", response_data);
7014
[email protected]5285d972011-10-18 18:56:347015 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557016 HttpStreamFactory::set_use_alternate_protocols(false);
7017}
7018
7019TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
7020 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347021 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2d6728692011-03-12 01:39:557022 SessionDependencies session_deps;
7023
7024 HttpRequestInfo request;
7025 request.method = "GET";
7026 request.url = GURL("http://www.google.com/");
7027 request.load_flags = 0;
7028
7029 MockRead data_reads[] = {
7030 MockRead("HTTP/1.1 200 OK\r\n"),
7031 MockRead(kAlternateProtocolHttpHeader),
7032 MockRead("hello world"),
7033 MockRead(true, OK),
7034 };
7035
7036 StaticSocketDataProvider first_transaction(
7037 data_reads, arraysize(data_reads), NULL, 0);
7038 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7039
7040 SSLSocketDataProvider ssl(true, OK);
7041 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7042 ssl.next_proto = "spdy/2";
7043 ssl.was_npn_negotiated = true;
7044 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7045
7046 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7047 StaticSocketDataProvider hanging_alternate_protocol_socket(
7048 NULL, 0, NULL, 0);
7049 hanging_alternate_protocol_socket.set_connect_data(
7050 never_finishing_connect);
7051 session_deps.socket_factory.AddSocketDataProvider(
7052 &hanging_alternate_protocol_socket);
7053
7054 // 2nd request is just a copy of the first one, over HTTP again.
7055 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7056
[email protected]f1f3f0f82011-10-01 20:38:107057 TestOldCompletionCallback callback;
[email protected]2d6728692011-03-12 01:39:557058
7059 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7060 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7061
7062 int rv = trans->Start(&request, &callback, BoundNetLog());
7063 EXPECT_EQ(ERR_IO_PENDING, rv);
7064 EXPECT_EQ(OK, callback.WaitForResult());
7065
7066 const HttpResponseInfo* response = trans->GetResponseInfo();
7067 ASSERT_TRUE(response != NULL);
7068 ASSERT_TRUE(response->headers != NULL);
7069 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7070
7071 std::string response_data;
7072 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7073 EXPECT_EQ("hello world", response_data);
7074
7075 trans.reset(new HttpNetworkTransaction(session));
7076
7077 rv = trans->Start(&request, &callback, BoundNetLog());
7078 EXPECT_EQ(ERR_IO_PENDING, rv);
7079 EXPECT_EQ(OK, callback.WaitForResult());
7080
7081 response = trans->GetResponseInfo();
7082 ASSERT_TRUE(response != NULL);
7083 ASSERT_TRUE(response->headers != NULL);
7084 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7085 EXPECT_FALSE(response->was_fetched_via_spdy);
7086 EXPECT_FALSE(response->was_npn_negotiated);
7087
7088 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7089 EXPECT_EQ("hello world", response_data);
7090
[email protected]5285d972011-10-18 18:56:347091 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]2d6728692011-03-12 01:39:557092 HttpStreamFactory::set_use_alternate_protocols(false);
7093}
7094
[email protected]631f1322010-04-30 17:59:117095class CapturingProxyResolver : public ProxyResolver {
7096 public:
7097 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
7098 virtual ~CapturingProxyResolver() {}
7099
7100 virtual int GetProxyForURL(const GURL& url,
7101 ProxyInfo* results,
[email protected]f1f3f0f82011-10-01 20:38:107102 OldCompletionCallback* callback,
[email protected]631f1322010-04-30 17:59:117103 RequestHandle* request,
7104 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:407105 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
7106 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:427107 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:117108 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:427109 return OK;
[email protected]631f1322010-04-30 17:59:117110 }
7111
7112 virtual void CancelRequest(RequestHandle request) {
7113 NOTREACHED();
7114 }
7115
[email protected]1e605472010-12-16 21:41:407116 virtual void CancelSetPacScript() {
7117 NOTREACHED();
7118 }
7119
[email protected]24476402010-07-20 20:55:177120 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]f1f3f0f82011-10-01 20:38:107121 OldCompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:427122 return OK;
[email protected]631f1322010-04-30 17:59:117123 }
7124
[email protected]24476402010-07-20 20:55:177125 const std::vector<GURL>& resolved() const { return resolved_; }
7126
7127 private:
[email protected]631f1322010-04-30 17:59:117128 std::vector<GURL> resolved_;
7129
7130 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
7131};
7132
[email protected]631f1322010-04-30 17:59:117133TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:387134 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347135 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]631f1322010-04-30 17:59:117136
7137 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:427138 proxy_config.set_auto_detect(true);
7139 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:117140
[email protected]631f1322010-04-30 17:59:117141 CapturingProxyResolver* capturing_proxy_resolver =
7142 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:387143 SessionDependencies session_deps(new ProxyService(
7144 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
7145 NULL));
[email protected]631f1322010-04-30 17:59:117146
7147 HttpRequestInfo request;
7148 request.method = "GET";
7149 request.url = GURL("http://www.google.com/");
7150 request.load_flags = 0;
7151
7152 MockRead data_reads[] = {
7153 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357154 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:117155 MockRead("hello world"),
7156 MockRead(true, OK),
7157 };
7158
7159 StaticSocketDataProvider first_transaction(
7160 data_reads, arraysize(data_reads), NULL, 0);
7161 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7162
7163 SSLSocketDataProvider ssl(true, OK);
7164 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357165 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537166 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:117167 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7168
[email protected]2bd93022010-07-17 00:58:447169 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:117170 MockWrite spdy_writes[] = {
7171 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7172 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:427173 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:137174 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:117175 };
7176
[email protected]d911f1b2010-05-05 22:39:427177 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7178
[email protected]2bd93022010-07-17 00:58:447179 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7180 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:117181 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:427182 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:137183 CreateMockRead(*resp.get(), 4), // 2, 4
7184 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:427185 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:117186 };
7187
[email protected]d911f1b2010-05-05 22:39:427188 scoped_refptr<OrderedSocketData> spdy_data(
7189 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:117190 spdy_reads, arraysize(spdy_reads),
7191 spdy_writes, arraysize(spdy_writes)));
7192 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7193
[email protected]2d6728692011-03-12 01:39:557194 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
7195 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
7196 NULL, 0, NULL, 0);
7197 hanging_non_alternate_protocol_socket.set_connect_data(
7198 never_finishing_connect);
7199 session_deps.socket_factory.AddSocketDataProvider(
7200 &hanging_non_alternate_protocol_socket);
7201
[email protected]f1f3f0f82011-10-01 20:38:107202 TestOldCompletionCallback callback;
[email protected]631f1322010-04-30 17:59:117203
7204 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7205 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7206
7207 int rv = trans->Start(&request, &callback, BoundNetLog());
7208 EXPECT_EQ(ERR_IO_PENDING, rv);
7209 EXPECT_EQ(OK, callback.WaitForResult());
7210
7211 const HttpResponseInfo* response = trans->GetResponseInfo();
7212 ASSERT_TRUE(response != NULL);
7213 ASSERT_TRUE(response->headers != NULL);
7214 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537215 EXPECT_FALSE(response->was_fetched_via_spdy);
7216 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117217
7218 std::string response_data;
7219 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7220 EXPECT_EQ("hello world", response_data);
7221
7222 trans.reset(new HttpNetworkTransaction(session));
7223
7224 rv = trans->Start(&request, &callback, BoundNetLog());
7225 EXPECT_EQ(ERR_IO_PENDING, rv);
7226 EXPECT_EQ(OK, callback.WaitForResult());
7227
7228 response = trans->GetResponseInfo();
7229 ASSERT_TRUE(response != NULL);
7230 ASSERT_TRUE(response->headers != NULL);
7231 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537232 EXPECT_TRUE(response->was_fetched_via_spdy);
7233 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:117234
7235 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7236 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:557237 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:427238 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:117239 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:427240 EXPECT_EQ("https://www.google.com/",
7241 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:117242
[email protected]5285d972011-10-18 18:56:347243 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387244 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:117245}
[email protected]631f1322010-04-30 17:59:117246
[email protected]2ff8b312010-04-26 22:20:547247TEST_F(HttpNetworkTransactionTest,
7248 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:387249 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:347250 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]2ff8b312010-04-26 22:20:547251 SessionDependencies session_deps;
7252
7253 HttpRequestInfo request;
7254 request.method = "GET";
7255 request.url = GURL("http://www.google.com/");
7256 request.load_flags = 0;
7257
7258 MockRead data_reads[] = {
7259 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357260 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:547261 MockRead("hello world"),
7262 MockRead(true, OK),
7263 };
7264
7265 StaticSocketDataProvider first_transaction(
7266 data_reads, arraysize(data_reads), NULL, 0);
7267 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7268
7269 SSLSocketDataProvider ssl(true, OK);
7270 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357271 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537272 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:547273 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537274 // Make sure we use ssl for spdy here.
7275 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547276
[email protected]2bd93022010-07-17 00:58:447277 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137278 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547279
[email protected]2bd93022010-07-17 00:58:447280 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7281 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547282 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137283 CreateMockRead(*resp),
7284 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547285 MockRead(true, 0, 0),
7286 };
7287
7288 scoped_refptr<DelayedSocketData> spdy_data(
7289 new DelayedSocketData(
7290 1, // wait for one write to finish before reading.
7291 spdy_reads, arraysize(spdy_reads),
7292 spdy_writes, arraysize(spdy_writes)));
7293 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7294
[email protected]f1f3f0f82011-10-01 20:38:107295 TestOldCompletionCallback callback;
[email protected]2ff8b312010-04-26 22:20:547296
7297 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7298
7299 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7300
[email protected]5a1d7ca2010-04-28 20:12:277301 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547302 EXPECT_EQ(ERR_IO_PENDING, rv);
7303 EXPECT_EQ(OK, callback.WaitForResult());
7304
7305 const HttpResponseInfo* response = trans->GetResponseInfo();
7306 ASSERT_TRUE(response != NULL);
7307 ASSERT_TRUE(response->headers != NULL);
7308 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7309
7310 std::string response_data;
7311 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7312 EXPECT_EQ("hello world", response_data);
7313
7314 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387315 HostPortPair host_port_pair("www.google.com", 443);
7316 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547317 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317318 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287319 scoped_refptr<TransportSocketParams> transport_params(
7320 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:387321
7322 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7323 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287324 connection->Init(host_port_pair.ToString(),
7325 transport_params,
7326 LOWEST,
7327 &callback,
7328 session->transport_socket_pool(),
[email protected]02b0c342010-09-25 21:09:387329 BoundNetLog()));
7330 EXPECT_EQ(OK, callback.WaitForResult());
7331
7332 SSLConfig ssl_config;
7333 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347334 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
[email protected]feb79bcd2011-07-21 16:55:177335 SSLClientSocketContext context;
7336 context.cert_verifier = session_deps.cert_verifier.get();
[email protected]9e1bdd32011-02-03 21:48:347337 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7338 connection.release(), HostPortPair("" , 443), ssl_config,
[email protected]feb79bcd2011-07-21 16:55:177339 NULL /* ssl_host_info */, context));
[email protected]9e1bdd32011-02-03 21:48:347340 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:387341 EXPECT_EQ(OK, callback.WaitForResult());
7342
[email protected]9e1bdd32011-02-03 21:48:347343 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387344 true, OK));
7345
[email protected]2ff8b312010-04-26 22:20:547346 trans.reset(new HttpNetworkTransaction(session));
7347
[email protected]5a1d7ca2010-04-28 20:12:277348 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547349 EXPECT_EQ(ERR_IO_PENDING, rv);
7350 EXPECT_EQ(OK, callback.WaitForResult());
7351
7352 response = trans->GetResponseInfo();
7353 ASSERT_TRUE(response != NULL);
7354 ASSERT_TRUE(response->headers != NULL);
7355 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537356 EXPECT_TRUE(response->was_fetched_via_spdy);
7357 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547358
7359 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7360 EXPECT_EQ("hello!", response_data);
7361
[email protected]5285d972011-10-18 18:56:347362 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:387363 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427364}
7365
[email protected]044de0642010-06-17 10:42:157366// GenerateAuthToken is a mighty big test.
7367// It tests all permutation of GenerateAuthToken behavior:
7368// - Synchronous and Asynchronous completion.
7369// - OK or error on completion.
7370// - Direct connection, non-authenticating proxy, and authenticating proxy.
7371// - HTTP or HTTPS backend (to include proxy tunneling).
7372// - Non-authenticating and authenticating backend.
7373//
7374// In all, there are 44 reasonable permuations (for example, if there are
7375// problems generating an auth token for an authenticating proxy, we don't
7376// need to test all permutations of the backend server).
7377//
7378// The test proceeds by going over each of the configuration cases, and
7379// potentially running up to three rounds in each of the tests. The TestConfig
7380// specifies both the configuration for the test as well as the expectations
7381// for the results.
7382TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507383 static const char kServer[] = "http://www.example.com";
7384 static const char kSecureServer[] = "https://www.example.com";
7385 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157386 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7387
7388 enum AuthTiming {
7389 AUTH_NONE,
7390 AUTH_SYNC,
7391 AUTH_ASYNC,
7392 };
7393
7394 const MockWrite kGet(
7395 "GET / HTTP/1.1\r\n"
7396 "Host: www.example.com\r\n"
7397 "Connection: keep-alive\r\n\r\n");
7398 const MockWrite kGetProxy(
7399 "GET http://www.example.com/ HTTP/1.1\r\n"
7400 "Host: www.example.com\r\n"
7401 "Proxy-Connection: keep-alive\r\n\r\n");
7402 const MockWrite kGetAuth(
7403 "GET / HTTP/1.1\r\n"
7404 "Host: www.example.com\r\n"
7405 "Connection: keep-alive\r\n"
7406 "Authorization: auth_token\r\n\r\n");
7407 const MockWrite kGetProxyAuth(
7408 "GET http://www.example.com/ HTTP/1.1\r\n"
7409 "Host: www.example.com\r\n"
7410 "Proxy-Connection: keep-alive\r\n"
7411 "Proxy-Authorization: auth_token\r\n\r\n");
7412 const MockWrite kGetAuthThroughProxy(
7413 "GET http://www.example.com/ HTTP/1.1\r\n"
7414 "Host: www.example.com\r\n"
7415 "Proxy-Connection: keep-alive\r\n"
7416 "Authorization: auth_token\r\n\r\n");
7417 const MockWrite kGetAuthWithProxyAuth(
7418 "GET http://www.example.com/ HTTP/1.1\r\n"
7419 "Host: www.example.com\r\n"
7420 "Proxy-Connection: keep-alive\r\n"
7421 "Proxy-Authorization: auth_token\r\n"
7422 "Authorization: auth_token\r\n\r\n");
7423 const MockWrite kConnect(
7424 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7425 "Host: www.example.com\r\n"
7426 "Proxy-Connection: keep-alive\r\n\r\n");
7427 const MockWrite kConnectProxyAuth(
7428 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7429 "Host: www.example.com\r\n"
7430 "Proxy-Connection: keep-alive\r\n"
7431 "Proxy-Authorization: auth_token\r\n\r\n");
7432
7433 const MockRead kSuccess(
7434 "HTTP/1.1 200 OK\r\n"
7435 "Content-Type: text/html; charset=iso-8859-1\r\n"
7436 "Content-Length: 3\r\n\r\n"
7437 "Yes");
7438 const MockRead kFailure(
7439 "Should not be called.");
7440 const MockRead kServerChallenge(
7441 "HTTP/1.1 401 Unauthorized\r\n"
7442 "WWW-Authenticate: Mock realm=server\r\n"
7443 "Content-Type: text/html; charset=iso-8859-1\r\n"
7444 "Content-Length: 14\r\n\r\n"
7445 "Unauthorized\r\n");
7446 const MockRead kProxyChallenge(
7447 "HTTP/1.1 407 Unauthorized\r\n"
7448 "Proxy-Authenticate: Mock realm=proxy\r\n"
7449 "Proxy-Connection: close\r\n"
7450 "Content-Type: text/html; charset=iso-8859-1\r\n"
7451 "Content-Length: 14\r\n\r\n"
7452 "Unauthorized\r\n");
7453 const MockRead kProxyConnected(
7454 "HTTP/1.1 200 Connection Established\r\n\r\n");
7455
7456 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7457 // no constructors, but the C++ compiler on Windows warns about
7458 // unspecified data in compound literals. So, moved to using constructors,
7459 // and TestRound's created with the default constructor should not be used.
7460 struct TestRound {
7461 TestRound()
7462 : expected_rv(ERR_UNEXPECTED),
7463 extra_write(NULL),
7464 extra_read(NULL) {
7465 }
7466 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7467 int expected_rv_arg)
7468 : write(write_arg),
7469 read(read_arg),
7470 expected_rv(expected_rv_arg),
7471 extra_write(NULL),
7472 extra_read(NULL) {
7473 }
7474 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7475 int expected_rv_arg, const MockWrite* extra_write_arg,
7476 const MockWrite* extra_read_arg)
7477 : write(write_arg),
7478 read(read_arg),
7479 expected_rv(expected_rv_arg),
7480 extra_write(extra_write_arg),
7481 extra_read(extra_read_arg) {
7482 }
7483 MockWrite write;
7484 MockRead read;
7485 int expected_rv;
7486 const MockWrite* extra_write;
7487 const MockRead* extra_read;
7488 };
7489
7490 static const int kNoSSL = 500;
7491
7492 struct TestConfig {
7493 const char* proxy_url;
7494 AuthTiming proxy_auth_timing;
7495 int proxy_auth_rv;
7496 const char* server_url;
7497 AuthTiming server_auth_timing;
7498 int server_auth_rv;
7499 int num_auth_rounds;
7500 int first_ssl_round;
7501 TestRound rounds[3];
7502 } test_configs[] = {
7503 // Non-authenticating HTTP server with a direct connection.
7504 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7505 { TestRound(kGet, kSuccess, OK)}},
7506 // Authenticating HTTP server with a direct connection.
7507 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7508 { TestRound(kGet, kServerChallenge, OK),
7509 TestRound(kGetAuth, kSuccess, OK)}},
7510 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7511 { TestRound(kGet, kServerChallenge, OK),
7512 TestRound(kGetAuth, kFailure, kAuthErr)}},
7513 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7514 { TestRound(kGet, kServerChallenge, OK),
7515 TestRound(kGetAuth, kSuccess, OK)}},
7516 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7517 { TestRound(kGet, kServerChallenge, OK),
7518 TestRound(kGetAuth, kFailure, kAuthErr)}},
7519 // Non-authenticating HTTP server through a non-authenticating proxy.
7520 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7521 { TestRound(kGetProxy, kSuccess, OK)}},
7522 // Authenticating HTTP server through a non-authenticating proxy.
7523 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7524 { TestRound(kGetProxy, kServerChallenge, OK),
7525 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7526 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7527 { TestRound(kGetProxy, kServerChallenge, OK),
7528 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7529 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7530 { TestRound(kGetProxy, kServerChallenge, OK),
7531 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7532 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7533 { TestRound(kGetProxy, kServerChallenge, OK),
7534 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7535 // Non-authenticating HTTP server through an authenticating proxy.
7536 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7537 { TestRound(kGetProxy, kProxyChallenge, OK),
7538 TestRound(kGetProxyAuth, kSuccess, OK)}},
7539 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7540 { TestRound(kGetProxy, kProxyChallenge, OK),
7541 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7542 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7543 { TestRound(kGetProxy, kProxyChallenge, OK),
7544 TestRound(kGetProxyAuth, kSuccess, OK)}},
7545 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7546 { TestRound(kGetProxy, kProxyChallenge, OK),
7547 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7548 // Authenticating HTTP server through an authenticating proxy.
7549 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7550 { TestRound(kGetProxy, kProxyChallenge, OK),
7551 TestRound(kGetProxyAuth, kServerChallenge, OK),
7552 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7553 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7554 { TestRound(kGetProxy, kProxyChallenge, OK),
7555 TestRound(kGetProxyAuth, kServerChallenge, OK),
7556 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7557 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7558 { TestRound(kGetProxy, kProxyChallenge, OK),
7559 TestRound(kGetProxyAuth, kServerChallenge, OK),
7560 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7561 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7562 { TestRound(kGetProxy, kProxyChallenge, OK),
7563 TestRound(kGetProxyAuth, kServerChallenge, OK),
7564 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7565 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7566 { TestRound(kGetProxy, kProxyChallenge, OK),
7567 TestRound(kGetProxyAuth, kServerChallenge, OK),
7568 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7569 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7570 { TestRound(kGetProxy, kProxyChallenge, OK),
7571 TestRound(kGetProxyAuth, kServerChallenge, OK),
7572 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7573 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7574 { TestRound(kGetProxy, kProxyChallenge, OK),
7575 TestRound(kGetProxyAuth, kServerChallenge, OK),
7576 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7577 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7578 { TestRound(kGetProxy, kProxyChallenge, OK),
7579 TestRound(kGetProxyAuth, kServerChallenge, OK),
7580 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7581 // Non-authenticating HTTPS server with a direct connection.
7582 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7583 { TestRound(kGet, kSuccess, OK)}},
7584 // Authenticating HTTPS server with a direct connection.
7585 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7586 { TestRound(kGet, kServerChallenge, OK),
7587 TestRound(kGetAuth, kSuccess, OK)}},
7588 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7589 { TestRound(kGet, kServerChallenge, OK),
7590 TestRound(kGetAuth, kFailure, kAuthErr)}},
7591 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7592 { TestRound(kGet, kServerChallenge, OK),
7593 TestRound(kGetAuth, kSuccess, OK)}},
7594 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7595 { TestRound(kGet, kServerChallenge, OK),
7596 TestRound(kGetAuth, kFailure, kAuthErr)}},
7597 // Non-authenticating HTTPS server with a non-authenticating proxy.
7598 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7599 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7600 // Authenticating HTTPS server through a non-authenticating proxy.
7601 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7602 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7603 TestRound(kGetAuth, kSuccess, OK)}},
7604 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7605 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7606 TestRound(kGetAuth, kFailure, kAuthErr)}},
7607 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7608 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7609 TestRound(kGetAuth, kSuccess, OK)}},
7610 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7611 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7612 TestRound(kGetAuth, kFailure, kAuthErr)}},
7613 // Non-Authenticating HTTPS server through an authenticating proxy.
7614 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7615 { TestRound(kConnect, kProxyChallenge, OK),
7616 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7617 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7618 { TestRound(kConnect, kProxyChallenge, OK),
7619 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7620 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7621 { TestRound(kConnect, kProxyChallenge, OK),
7622 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7623 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7624 { TestRound(kConnect, kProxyChallenge, OK),
7625 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7626 // Authenticating HTTPS server through an authenticating proxy.
7627 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7628 { TestRound(kConnect, kProxyChallenge, OK),
7629 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7630 &kGet, &kServerChallenge),
7631 TestRound(kGetAuth, kSuccess, OK)}},
7632 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7633 { TestRound(kConnect, kProxyChallenge, OK),
7634 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7635 &kGet, &kServerChallenge),
7636 TestRound(kGetAuth, kFailure, kAuthErr)}},
7637 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7638 { TestRound(kConnect, kProxyChallenge, OK),
7639 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7640 &kGet, &kServerChallenge),
7641 TestRound(kGetAuth, kSuccess, OK)}},
7642 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7643 { TestRound(kConnect, kProxyChallenge, OK),
7644 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7645 &kGet, &kServerChallenge),
7646 TestRound(kGetAuth, kFailure, kAuthErr)}},
7647 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7648 { TestRound(kConnect, kProxyChallenge, OK),
7649 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7650 &kGet, &kServerChallenge),
7651 TestRound(kGetAuth, kSuccess, OK)}},
7652 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7653 { TestRound(kConnect, kProxyChallenge, OK),
7654 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7655 &kGet, &kServerChallenge),
7656 TestRound(kGetAuth, kFailure, kAuthErr)}},
7657 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7658 { TestRound(kConnect, kProxyChallenge, OK),
7659 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7660 &kGet, &kServerChallenge),
7661 TestRound(kGetAuth, kSuccess, OK)}},
7662 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7663 { TestRound(kConnect, kProxyChallenge, OK),
7664 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7665 &kGet, &kServerChallenge),
7666 TestRound(kGetAuth, kFailure, kAuthErr)}},
7667 };
7668
7669 SessionDependencies session_deps;
[email protected]044de0642010-06-17 10:42:157670 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
[email protected]2d01c262011-08-11 23:07:087671 HttpAuthHandlerMock::Factory* auth_factory(
7672 new HttpAuthHandlerMock::Factory());
7673 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]044de0642010-06-17 10:42:157674 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267675
7676 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157677 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]2d01c262011-08-11 23:07:087678 for (int n = 0; n < 2; n++) {
7679 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7680 std::string auth_challenge = "Mock realm=proxy";
7681 GURL origin(test_config.proxy_url);
7682 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7683 auth_challenge.end());
7684 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7685 origin, BoundNetLog());
7686 auth_handler->SetGenerateExpectation(
7687 test_config.proxy_auth_timing == AUTH_ASYNC,
7688 test_config.proxy_auth_rv);
7689 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
7690 }
[email protected]044de0642010-06-17 10:42:157691 }
7692 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007693 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157694 std::string auth_challenge = "Mock realm=server";
7695 GURL origin(test_config.server_url);
7696 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7697 auth_challenge.end());
7698 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7699 origin, BoundNetLog());
7700 auth_handler->SetGenerateExpectation(
7701 test_config.server_auth_timing == AUTH_ASYNC,
7702 test_config.server_auth_rv);
[email protected]2d01c262011-08-11 23:07:087703 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]044de0642010-06-17 10:42:157704 }
7705 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127706 session_deps.proxy_service.reset(
7707 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157708 } else {
[email protected]6104ea5d2011-04-27 21:37:127709 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157710 }
7711
7712 HttpRequestInfo request;
7713 request.method = "GET";
7714 request.url = GURL(test_config.server_url);
7715 request.load_flags = 0;
7716
[email protected]0b0bf032010-09-21 18:08:507717 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7718 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157719
7720 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7721 const TestRound& read_write_round = test_config.rounds[round];
7722
7723 // Set up expected reads and writes.
7724 MockRead reads[2];
7725 reads[0] = read_write_round.read;
7726 size_t length_reads = 1;
7727 if (read_write_round.extra_read) {
7728 reads[1] = *read_write_round.extra_read;
7729 length_reads = 2;
7730 }
7731
7732 MockWrite writes[2];
7733 writes[0] = read_write_round.write;
7734 size_t length_writes = 1;
7735 if (read_write_round.extra_write) {
7736 writes[1] = *read_write_round.extra_write;
7737 length_writes = 2;
7738 }
7739 StaticSocketDataProvider data_provider(
7740 reads, length_reads, writes, length_writes);
7741 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7742
7743 // Add an SSL sequence if necessary.
7744 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7745 if (round >= test_config.first_ssl_round)
7746 session_deps.socket_factory.AddSSLSocketDataProvider(
7747 &ssl_socket_data_provider);
7748
7749 // Start or restart the transaction.
[email protected]f1f3f0f82011-10-01 20:38:107750 TestOldCompletionCallback callback;
[email protected]044de0642010-06-17 10:42:157751 int rv;
7752 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507753 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157754 } else {
[email protected]0b0bf032010-09-21 18:08:507755 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157756 }
7757 if (rv == ERR_IO_PENDING)
7758 rv = callback.WaitForResult();
7759
7760 // Compare results with expected data.
7761 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507762 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157763 if (read_write_round.expected_rv == OK) {
[email protected]fe2255a2011-09-20 19:37:507764 ASSERT_TRUE(response != NULL);
[email protected]044de0642010-06-17 10:42:157765 } else {
7766 EXPECT_TRUE(response == NULL);
7767 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7768 continue;
7769 }
7770 if (round + 1 < test_config.num_auth_rounds) {
7771 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7772 } else {
7773 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7774 }
7775 }
[email protected]e5ae96a2010-04-14 20:12:457776 }
7777}
7778
[email protected]c871bce92010-07-15 21:51:147779TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7780 // Do multi-round authentication and make sure it works correctly.
7781 SessionDependencies session_deps;
7782 HttpAuthHandlerMock::Factory* auth_factory(
7783 new HttpAuthHandlerMock::Factory());
7784 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127785 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147786 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7787 session_deps.host_resolver->set_synchronous_mode(true);
7788
7789 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7790 auth_handler->set_connection_based(true);
7791 std::string auth_challenge = "Mock realm=server";
7792 GURL origin("http://www.example.com");
7793 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7794 auth_challenge.end());
7795 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7796 origin, BoundNetLog());
[email protected]2d01c262011-08-11 23:07:087797 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_SERVER);
[email protected]c871bce92010-07-15 21:51:147798
[email protected]c871bce92010-07-15 21:51:147799 int rv = OK;
7800 const HttpResponseInfo* response = NULL;
7801 HttpRequestInfo request;
7802 request.method = "GET";
7803 request.url = origin;
7804 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277805
7806 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107807
7808 // Use a TCP Socket Pool with only one connection per group. This is used
7809 // to validate that the TCP socket is not released to the pool between
7810 // each round of multi-round authentication.
7811 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287812 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7813 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107814 50, // Max sockets for pool
7815 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287816 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107817 session_deps.host_resolver.get(),
7818 &session_deps.socket_factory,
7819 session_deps.net_log);
[email protected]ab739042011-04-07 15:22:287820 session_peer.SetTransportSocketPool(transport_pool);
[email protected]7ef4cbbb2011-02-06 11:19:107821
[email protected]cb9bf6ca2011-01-28 13:15:277822 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:107823 TestOldCompletionCallback callback;
[email protected]c871bce92010-07-15 21:51:147824
7825 const MockWrite kGet(
7826 "GET / HTTP/1.1\r\n"
7827 "Host: www.example.com\r\n"
7828 "Connection: keep-alive\r\n\r\n");
7829 const MockWrite kGetAuth(
7830 "GET / HTTP/1.1\r\n"
7831 "Host: www.example.com\r\n"
7832 "Connection: keep-alive\r\n"
7833 "Authorization: auth_token\r\n\r\n");
7834
7835 const MockRead kServerChallenge(
7836 "HTTP/1.1 401 Unauthorized\r\n"
7837 "WWW-Authenticate: Mock realm=server\r\n"
7838 "Content-Type: text/html; charset=iso-8859-1\r\n"
7839 "Content-Length: 14\r\n\r\n"
7840 "Unauthorized\r\n");
7841 const MockRead kSuccess(
7842 "HTTP/1.1 200 OK\r\n"
7843 "Content-Type: text/html; charset=iso-8859-1\r\n"
7844 "Content-Length: 3\r\n\r\n"
7845 "Yes");
7846
7847 MockWrite writes[] = {
7848 // First round
7849 kGet,
7850 // Second round
7851 kGetAuth,
7852 // Third round
7853 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307854 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107855 kGetAuth,
7856 // Competing request
7857 kGet,
[email protected]c871bce92010-07-15 21:51:147858 };
7859 MockRead reads[] = {
7860 // First round
7861 kServerChallenge,
7862 // Second round
7863 kServerChallenge,
7864 // Third round
[email protected]eca50e122010-09-11 14:03:307865 kServerChallenge,
7866 // Fourth round
[email protected]c871bce92010-07-15 21:51:147867 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107868 // Competing response
7869 kSuccess,
[email protected]c871bce92010-07-15 21:51:147870 };
7871 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7872 writes, arraysize(writes));
7873 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7874
[email protected]7ef4cbbb2011-02-06 11:19:107875 const char* const kSocketGroup = "www.example.com:80";
7876
7877 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147878 auth_handler->SetGenerateExpectation(false, OK);
7879 rv = trans->Start(&request, &callback, BoundNetLog());
7880 if (rv == ERR_IO_PENDING)
7881 rv = callback.WaitForResult();
7882 EXPECT_EQ(OK, rv);
7883 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507884 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147885 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287886 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147887
[email protected]7ef4cbbb2011-02-06 11:19:107888 // In between rounds, another request comes in for the same domain.
7889 // It should not be able to grab the TCP socket that trans has already
7890 // claimed.
7891 scoped_ptr<HttpTransaction> trans_compete(
7892 new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:107893 TestOldCompletionCallback callback_compete;
[email protected]7ef4cbbb2011-02-06 11:19:107894 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7895 EXPECT_EQ(ERR_IO_PENDING, rv);
7896 // callback_compete.WaitForResult at this point would stall forever,
7897 // since the HttpNetworkTransaction does not release the request back to
7898 // the pool until after authentication completes.
7899
7900 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147901 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447902 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147903 if (rv == ERR_IO_PENDING)
7904 rv = callback.WaitForResult();
7905 EXPECT_EQ(OK, rv);
7906 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507907 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147908 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287909 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147910
[email protected]7ef4cbbb2011-02-06 11:19:107911 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147912 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447913 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147914 if (rv == ERR_IO_PENDING)
7915 rv = callback.WaitForResult();
7916 EXPECT_EQ(OK, rv);
7917 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507918 ASSERT_TRUE(response != NULL);
[email protected]c871bce92010-07-15 21:51:147919 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287920 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307921
[email protected]7ef4cbbb2011-02-06 11:19:107922 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307923 auth_handler->SetGenerateExpectation(false, OK);
7924 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7925 if (rv == ERR_IO_PENDING)
7926 rv = callback.WaitForResult();
7927 EXPECT_EQ(OK, rv);
7928 response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:507929 ASSERT_TRUE(response != NULL);
[email protected]eca50e122010-09-11 14:03:307930 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287931 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107932
7933 // Read the body since the fourth round was successful. This will also
7934 // release the socket back to the pool.
7935 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7936 rv = trans->Read(io_buf, io_buf->size(), &callback);
7937 if (rv == ERR_IO_PENDING)
7938 rv = callback.WaitForResult();
7939 EXPECT_EQ(3, rv);
7940 rv = trans->Read(io_buf, io_buf->size(), &callback);
7941 EXPECT_EQ(0, rv);
7942 // There are still 0 idle sockets, since the trans_compete transaction
7943 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287944 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107945
7946 // The competing request can now finish. Wait for the headers and then
7947 // read the body.
7948 rv = callback_compete.WaitForResult();
7949 EXPECT_EQ(OK, rv);
7950 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7951 if (rv == ERR_IO_PENDING)
7952 rv = callback.WaitForResult();
7953 EXPECT_EQ(3, rv);
7954 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7955 EXPECT_EQ(0, rv);
7956
7957 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287958 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147959}
7960
[email protected]aeaca1f2010-04-20 22:05:217961class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7962 public:
[email protected]06650c52010-06-03 00:49:177963 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217964 : fail_all_(fail_all) {
7965 }
7966
7967 virtual MockRead GetNextRead() {
7968 if (fail_all_)
7969 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7970
7971 return MockRead(false /* async */,
7972 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7973 }
7974
7975 virtual MockWriteResult OnWrite(const std::string& data) {
7976 return MockWriteResult(false /* async */, data.size());
7977 }
7978
7979 void Reset() {
7980 }
7981
7982 private:
7983 const bool fail_all_;
7984};
7985
7986// Test that we restart a connection when we see a decompression failure from
7987// the peer during the handshake. (In the real world we'll restart with SSLv3
7988// and we won't offer DEFLATE in that case.)
7989TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7990 HttpRequestInfo request;
7991 request.method = "GET";
7992 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7993 request.load_flags = 0;
7994
7995 SessionDependencies session_deps;
7996 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7997 false /* fail all reads */);
7998 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7999 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:118000 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:218001 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
8002 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8003 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8004 session_deps.socket_factory.AddSSLSocketDataProvider(
8005 &ssl_socket_data_provider1);
8006 session_deps.socket_factory.AddSSLSocketDataProvider(
8007 &ssl_socket_data_provider2);
8008
[email protected]e60e47a2010-07-14 03:37:188009 // Work around http://crbug.com/37454
8010 StaticSocketDataProvider bug37454_connection;
8011 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
8012 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
8013
[email protected]aeaca1f2010-04-20 22:05:218014 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8015 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:108016 TestOldCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218017
[email protected]5a1d7ca2010-04-28 20:12:278018 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218019 EXPECT_EQ(ERR_IO_PENDING, rv);
8020 EXPECT_EQ(OK, callback.WaitForResult());
8021
8022 const HttpResponseInfo* response = trans->GetResponseInfo();
8023 ASSERT_TRUE(response != NULL);
8024 ASSERT_TRUE(response->headers != NULL);
8025 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8026
8027 std::string response_data;
8028 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8029 EXPECT_EQ("ok.", response_data);
8030}
8031
8032// Test that we restart a connection if we get a decompression failure from the
8033// peer while reading the first bytes from the connection. This occurs when the
8034// peer cannot handle DEFLATE but we're using False Start, so we don't notice
8035// in the handshake.
8036TEST_F(HttpNetworkTransactionTest,
8037 RestartAfterTLSDecompressionFailureWithFalseStart) {
8038 HttpRequestInfo request;
8039 request.method = "GET";
8040 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
8041 request.load_flags = 0;
8042
8043 SessionDependencies session_deps;
8044 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
8045 true /* fail all reads */);
8046 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
8047 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
8048 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
8049 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
8050 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
8051 session_deps.socket_factory.AddSSLSocketDataProvider(
8052 &ssl_socket_data_provider1);
8053 session_deps.socket_factory.AddSSLSocketDataProvider(
8054 &ssl_socket_data_provider2);
8055
8056 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8057 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f1f3f0f82011-10-01 20:38:108058 TestOldCompletionCallback callback;
[email protected]aeaca1f2010-04-20 22:05:218059
[email protected]5a1d7ca2010-04-28 20:12:278060 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:218061 EXPECT_EQ(ERR_IO_PENDING, rv);
8062 EXPECT_EQ(OK, callback.WaitForResult());
8063
8064 const HttpResponseInfo* response = trans->GetResponseInfo();
8065 ASSERT_TRUE(response != NULL);
8066 ASSERT_TRUE(response->headers != NULL);
8067 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8068
8069 std::string response_data;
8070 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8071 EXPECT_EQ("ok.", response_data);
8072}
8073
[email protected]65041fa2010-05-21 06:56:538074// This tests the case that a request is issued via http instead of spdy after
8075// npn is negotiated.
8076TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:388077 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348078 HttpStreamFactory::set_next_protos(
8079 MakeNextProtos("http/1.1", "http1.1", NULL));
[email protected]65041fa2010-05-21 06:56:538080 SessionDependencies session_deps;
8081 HttpRequestInfo request;
8082 request.method = "GET";
8083 request.url = GURL("https://www.google.com/");
8084 request.load_flags = 0;
8085
8086 MockWrite data_writes[] = {
8087 MockWrite("GET / HTTP/1.1\r\n"
8088 "Host: www.google.com\r\n"
8089 "Connection: keep-alive\r\n\r\n"),
8090 };
8091
8092 MockRead data_reads[] = {
8093 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:358094 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:538095 MockRead("hello world"),
8096 MockRead(false, OK),
8097 };
8098
8099 SSLSocketDataProvider ssl(true, OK);
8100 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8101 ssl.next_proto = "http/1.1";
8102
8103 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8104
8105 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
8106 data_writes, arraysize(data_writes));
8107 session_deps.socket_factory.AddSocketDataProvider(&data);
8108
[email protected]f1f3f0f82011-10-01 20:38:108109 TestOldCompletionCallback callback;
[email protected]65041fa2010-05-21 06:56:538110
8111 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8112 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8113
8114 int rv = trans->Start(&request, &callback, BoundNetLog());
8115
8116 EXPECT_EQ(ERR_IO_PENDING, rv);
8117 EXPECT_EQ(OK, callback.WaitForResult());
8118
8119 const HttpResponseInfo* response = trans->GetResponseInfo();
8120 ASSERT_TRUE(response != NULL);
8121 ASSERT_TRUE(response->headers != NULL);
8122 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
8123
8124 std::string response_data;
8125 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
8126 EXPECT_EQ("hello world", response_data);
8127
8128 EXPECT_FALSE(response->was_fetched_via_spdy);
8129 EXPECT_TRUE(response->was_npn_negotiated);
8130
[email protected]5285d972011-10-18 18:56:348131 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388132 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:538133}
[email protected]26ef6582010-06-24 02:30:478134
8135TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
8136 // Simulate the SSL handshake completing with an NPN negotiation
8137 // followed by an immediate server closing of the socket.
8138 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:388139 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348140 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]26ef6582010-06-24 02:30:478141 SessionDependencies session_deps;
8142
8143 HttpRequestInfo request;
8144 request.method = "GET";
8145 request.url = GURL("https://www.google.com/");
8146 request.load_flags = 0;
8147
8148 SSLSocketDataProvider ssl(true, OK);
8149 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:358150 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:478151 ssl.was_npn_negotiated = true;
8152 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8153
[email protected]2bd93022010-07-17 00:58:448154 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:138155 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:478156
8157 MockRead spdy_reads[] = {
8158 MockRead(false, 0, 0) // Not async - return 0 immediately.
8159 };
8160
8161 scoped_refptr<DelayedSocketData> spdy_data(
8162 new DelayedSocketData(
8163 0, // don't wait in this case, immediate hangup.
8164 spdy_reads, arraysize(spdy_reads),
8165 spdy_writes, arraysize(spdy_writes)));
8166 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8167
[email protected]f1f3f0f82011-10-01 20:38:108168 TestOldCompletionCallback callback;
[email protected]26ef6582010-06-24 02:30:478169
8170 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8171 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8172
8173 int rv = trans->Start(&request, &callback, BoundNetLog());
8174 EXPECT_EQ(ERR_IO_PENDING, rv);
8175 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
8176
[email protected]5285d972011-10-18 18:56:348177 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388178 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:478179}
[email protected]65d34382010-07-01 18:12:268180
[email protected]f45c1ee2010-08-03 00:54:308181TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
8182 // This test ensures that the URL passed into the proxy is upgraded
8183 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:388184 HttpStreamFactory::set_use_alternate_protocols(true);
8185 HttpStreamFactory::set_next_protos(
[email protected]5285d972011-10-18 18:56:348186 MakeNextProtos("http/1.1", "http1.1", "spdy/2", "spdy", NULL));
[email protected]f45c1ee2010-08-03 00:54:308187
[email protected]81cdfcd2010-10-16 00:49:008188 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:308189 HttpAuthHandlerMock::Factory* auth_factory =
8190 new HttpAuthHandlerMock::Factory();
8191 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
[email protected]2d01c262011-08-11 23:07:088192 auth_factory->AddMockHandler(auth_handler, HttpAuth::AUTH_PROXY);
[email protected]f45c1ee2010-08-03 00:54:308193 auth_factory->set_do_init_from_challenge(true);
8194 session_deps.http_auth_handler_factory.reset(auth_factory);
8195
8196 HttpRequestInfo request;
8197 request.method = "GET";
8198 request.url = GURL("http://www.google.com");
8199 request.load_flags = 0;
8200
8201 // First round goes unauthenticated through the proxy.
8202 MockWrite data_writes_1[] = {
8203 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8204 "Host: www.google.com\r\n"
8205 "Proxy-Connection: keep-alive\r\n"
8206 "\r\n"),
8207 };
8208 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:598209 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:308210 MockRead("HTTP/1.1 200 OK\r\n"
8211 "Alternate-Protocol: 443:npn-spdy/2\r\n"
8212 "Proxy-Connection: close\r\n"
8213 "\r\n"),
8214 };
8215 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
8216 data_writes_1, arraysize(data_writes_1));
8217
8218 // Second round tries to tunnel to www.google.com due to the
8219 // Alternate-Protocol announcement in the first round. It fails due
8220 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:598221 // After the failure, a tunnel is established to www.google.com using
8222 // Proxy-Authorization headers. There is then a SPDY request round.
8223 //
8224 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
8225 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
8226 // does a Disconnect and Connect on the same socket, rather than trying
8227 // to obtain a new one.
8228 //
8229 // NOTE: Originally, the proxy response to the second CONNECT request
8230 // simply returned another 407 so the unit test could skip the SSL connection
8231 // establishment and SPDY framing issues. Alas, the
8232 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:308233 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:598234
[email protected]f45c1ee2010-08-03 00:54:308235 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
8236 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8237 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8238
[email protected]394816e92010-08-03 07:38:598239 MockWrite data_writes_2[] = {
8240 // First connection attempt without Proxy-Authorization.
8241 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8242 "Host: www.google.com\r\n"
8243 "Proxy-Connection: keep-alive\r\n"
8244 "\r\n"),
8245
8246 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:308247 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8248 "Host: www.google.com\r\n"
8249 "Proxy-Connection: keep-alive\r\n"
8250 "Proxy-Authorization: auth_token\r\n"
8251 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:308252
[email protected]394816e92010-08-03 07:38:598253 // SPDY request
8254 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:308255 };
[email protected]394816e92010-08-03 07:38:598256 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
8257 "Proxy-Authenticate: Mock\r\n"
8258 "Proxy-Connection: close\r\n"
8259 "\r\n");
8260 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
8261 MockRead data_reads_2[] = {
8262 // First connection attempt fails
8263 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
8264 MockRead(true, kRejectConnectResponse,
8265 arraysize(kRejectConnectResponse) - 1, 1),
8266
8267 // Second connection attempt passes
8268 MockRead(true, kAcceptConnectResponse,
8269 arraysize(kAcceptConnectResponse) -1, 4),
8270
8271 // SPDY response
8272 CreateMockRead(*resp.get(), 6),
8273 CreateMockRead(*data.get(), 6),
8274 MockRead(true, 0, 0, 6),
8275 };
8276 scoped_refptr<OrderedSocketData> data_2(
8277 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8278 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308279
8280 SSLSocketDataProvider ssl(true, OK);
8281 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8282 ssl.next_proto = "spdy/2";
8283 ssl.was_npn_negotiated = true;
8284
[email protected]2d6728692011-03-12 01:39:558285 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8286 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8287 NULL, 0, NULL, 0);
8288 hanging_non_alternate_protocol_socket.set_connect_data(
8289 never_finishing_connect);
8290
[email protected]f45c1ee2010-08-03 00:54:308291 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598292 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308293 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558294 session_deps.socket_factory.AddSocketDataProvider(
8295 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308296 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8297
8298 // First round should work and provide the Alternate-Protocol state.
[email protected]f1f3f0f82011-10-01 20:38:108299 TestOldCompletionCallback callback_1;
[email protected]f45c1ee2010-08-03 00:54:308300 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8301 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8302 EXPECT_EQ(ERR_IO_PENDING, rv);
8303 EXPECT_EQ(OK, callback_1.WaitForResult());
8304
8305 // Second round should attempt a tunnel connect and get an auth challenge.
[email protected]f1f3f0f82011-10-01 20:38:108306 TestOldCompletionCallback callback_2;
[email protected]f45c1ee2010-08-03 00:54:308307 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8308 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8309 EXPECT_EQ(ERR_IO_PENDING, rv);
8310 EXPECT_EQ(OK, callback_2.WaitForResult());
8311 const HttpResponseInfo* response = trans_2->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508312 ASSERT_TRUE(response != NULL);
[email protected]f45c1ee2010-08-03 00:54:308313 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8314
8315 // Restart with auth. Tunnel should work and response received.
[email protected]f1f3f0f82011-10-01 20:38:108316 TestOldCompletionCallback callback_3;
[email protected]f45c1ee2010-08-03 00:54:308317 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
8318 EXPECT_EQ(ERR_IO_PENDING, rv);
8319 EXPECT_EQ(OK, callback_3.WaitForResult());
8320
8321 // After all that work, these two lines (or actually, just the scheme) are
8322 // what this test is all about. Make sure it happens correctly.
8323 const GURL& request_url = auth_handler->request_url();
8324 EXPECT_EQ("https", request_url.scheme());
8325 EXPECT_EQ("www.google.com", request_url.host());
8326
[email protected]5285d972011-10-18 18:56:348327 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]8e6441ca2010-08-19 05:56:388328 HttpStreamFactory::set_use_alternate_protocols(false);
8329}
8330
8331// Test that if we cancel the transaction as the connection is completing, that
8332// everything tears down correctly.
8333TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8334 // Setup everything about the connection to complete synchronously, so that
8335 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8336 // for is the callback from the HttpStreamRequest.
8337 // Then cancel the transaction.
8338 // Verify that we don't crash.
8339 MockConnect mock_connect(false, OK);
8340 MockRead data_reads[] = {
8341 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8342 MockRead(false, "hello world"),
8343 MockRead(false, OK),
8344 };
8345
[email protected]8e6441ca2010-08-19 05:56:388346 HttpRequestInfo request;
8347 request.method = "GET";
8348 request.url = GURL("http://www.google.com/");
8349 request.load_flags = 0;
8350
[email protected]cb9bf6ca2011-01-28 13:15:278351 SessionDependencies session_deps;
8352 session_deps.host_resolver->set_synchronous_mode(true);
8353 scoped_ptr<HttpTransaction> trans(
8354 new HttpNetworkTransaction(CreateSession(&session_deps)));
8355
[email protected]8e6441ca2010-08-19 05:56:388356 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8357 data.set_connect_data(mock_connect);
8358 session_deps.socket_factory.AddSocketDataProvider(&data);
8359
[email protected]f1f3f0f82011-10-01 20:38:108360 TestOldCompletionCallback callback;
[email protected]8e6441ca2010-08-19 05:56:388361
8362 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8363 int rv = trans->Start(&request, &callback, log.bound());
8364 EXPECT_EQ(ERR_IO_PENDING, rv);
8365 trans.reset(); // Cancel the transaction here.
8366
8367 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308368}
8369
[email protected]76a505b2010-08-25 06:23:008370// Test a basic GET request through a proxy.
8371TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008372 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008373 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8374 session_deps.net_log = log.bound().net_log();
8375 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8376
[email protected]76a505b2010-08-25 06:23:008377 HttpRequestInfo request;
8378 request.method = "GET";
8379 request.url = GURL("http://www.google.com/");
8380
8381 MockWrite data_writes1[] = {
8382 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8383 "Host: www.google.com\r\n"
8384 "Proxy-Connection: keep-alive\r\n\r\n"),
8385 };
8386
8387 MockRead data_reads1[] = {
8388 MockRead("HTTP/1.1 200 OK\r\n"),
8389 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8390 MockRead("Content-Length: 100\r\n\r\n"),
8391 MockRead(false, OK),
8392 };
8393
8394 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8395 data_writes1, arraysize(data_writes1));
8396 session_deps.socket_factory.AddSocketDataProvider(&data1);
8397
[email protected]f1f3f0f82011-10-01 20:38:108398 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008399
[email protected]0b0bf032010-09-21 18:08:508400 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8401
[email protected]76a505b2010-08-25 06:23:008402 int rv = trans->Start(&request, &callback1, log.bound());
8403 EXPECT_EQ(ERR_IO_PENDING, rv);
8404
8405 rv = callback1.WaitForResult();
8406 EXPECT_EQ(OK, rv);
8407
8408 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508409 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008410
8411 EXPECT_TRUE(response->headers->IsKeepAlive());
8412 EXPECT_EQ(200, response->headers->response_code());
8413 EXPECT_EQ(100, response->headers->GetContentLength());
8414 EXPECT_TRUE(response->was_fetched_via_proxy);
8415 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8416}
8417
8418// Test a basic HTTPS GET request through a proxy.
8419TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008420 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008421 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8422 session_deps.net_log = log.bound().net_log();
8423 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8424
[email protected]76a505b2010-08-25 06:23:008425 HttpRequestInfo request;
8426 request.method = "GET";
8427 request.url = GURL("https://www.google.com/");
8428
8429 // Since we have proxy, should try to establish tunnel.
8430 MockWrite data_writes1[] = {
8431 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8432 "Host: www.google.com\r\n"
8433 "Proxy-Connection: keep-alive\r\n\r\n"),
8434
8435 MockWrite("GET / HTTP/1.1\r\n"
8436 "Host: www.google.com\r\n"
8437 "Connection: keep-alive\r\n\r\n"),
8438 };
8439
8440 MockRead data_reads1[] = {
8441 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8442
8443 MockRead("HTTP/1.1 200 OK\r\n"),
8444 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8445 MockRead("Content-Length: 100\r\n\r\n"),
8446 MockRead(false, OK),
8447 };
8448
8449 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8450 data_writes1, arraysize(data_writes1));
8451 session_deps.socket_factory.AddSocketDataProvider(&data1);
8452 SSLSocketDataProvider ssl(true, OK);
8453 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8454
[email protected]f1f3f0f82011-10-01 20:38:108455 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008456
[email protected]0b0bf032010-09-21 18:08:508457 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8458
[email protected]76a505b2010-08-25 06:23:008459 int rv = trans->Start(&request, &callback1, log.bound());
8460 EXPECT_EQ(ERR_IO_PENDING, rv);
8461
8462 rv = callback1.WaitForResult();
8463 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408464 net::CapturingNetLog::EntryList entries;
8465 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008466 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408467 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008468 NetLog::PHASE_NONE);
8469 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408470 entries, pos,
[email protected]76a505b2010-08-25 06:23:008471 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8472 NetLog::PHASE_NONE);
8473
8474 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]fe2255a2011-09-20 19:37:508475 ASSERT_TRUE(response != NULL);
[email protected]76a505b2010-08-25 06:23:008476
8477 EXPECT_TRUE(response->headers->IsKeepAlive());
8478 EXPECT_EQ(200, response->headers->response_code());
8479 EXPECT_EQ(100, response->headers->GetContentLength());
8480 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8481 EXPECT_TRUE(response->was_fetched_via_proxy);
8482}
8483
8484// Test a basic HTTPS GET request through a proxy, but the server hangs up
8485// while establishing the tunnel.
8486TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008487 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008488 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8489 session_deps.net_log = log.bound().net_log();
8490 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8491
[email protected]76a505b2010-08-25 06:23:008492 HttpRequestInfo request;
8493 request.method = "GET";
8494 request.url = GURL("https://www.google.com/");
8495
8496 // Since we have proxy, should try to establish tunnel.
8497 MockWrite data_writes1[] = {
8498 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8499 "Host: www.google.com\r\n"
8500 "Proxy-Connection: keep-alive\r\n\r\n"),
8501
8502 MockWrite("GET / HTTP/1.1\r\n"
8503 "Host: www.google.com\r\n"
8504 "Connection: keep-alive\r\n\r\n"),
8505 };
8506
8507 MockRead data_reads1[] = {
8508 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8509 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8510 MockRead(true, 0, 0), // EOF
8511 };
8512
8513 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8514 data_writes1, arraysize(data_writes1));
8515 session_deps.socket_factory.AddSocketDataProvider(&data1);
8516 SSLSocketDataProvider ssl(true, OK);
8517 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8518
[email protected]f1f3f0f82011-10-01 20:38:108519 TestOldCompletionCallback callback1;
[email protected]76a505b2010-08-25 06:23:008520
[email protected]0b0bf032010-09-21 18:08:508521 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8522
[email protected]76a505b2010-08-25 06:23:008523 int rv = trans->Start(&request, &callback1, log.bound());
8524 EXPECT_EQ(ERR_IO_PENDING, rv);
8525
8526 rv = callback1.WaitForResult();
8527 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408528 net::CapturingNetLog::EntryList entries;
8529 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008530 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408531 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008532 NetLog::PHASE_NONE);
8533 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408534 entries, pos,
[email protected]76a505b2010-08-25 06:23:008535 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8536 NetLog::PHASE_NONE);
8537}
8538
[email protected]749eefa82010-09-13 22:14:038539// Test for crbug.com/55424.
8540TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8541 SessionDependencies session_deps;
8542
8543 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8544 "https://www.google.com", false, 1, LOWEST));
8545 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8546
8547 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8548 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8549 MockRead spdy_reads[] = {
8550 CreateMockRead(*resp),
8551 CreateMockRead(*data),
8552 MockRead(true, 0, 0),
8553 };
8554
8555 scoped_refptr<DelayedSocketData> spdy_data(
8556 new DelayedSocketData(
8557 1, // wait for one write to finish before reading.
8558 spdy_reads, arraysize(spdy_reads),
8559 spdy_writes, arraysize(spdy_writes)));
8560 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8561
8562 SSLSocketDataProvider ssl(true, OK);
8563 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8564 ssl.next_proto = "spdy/2";
8565 ssl.was_npn_negotiated = true;
8566 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8567
8568 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8569
8570 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388571 HostPortPair host_port_pair("www.google.com", 443);
8572 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038573 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318574 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288575 scoped_refptr<TransportSocketParams> transport_params(
8576 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]f1f3f0f82011-10-01 20:38:108577 TestOldCompletionCallback callback;
[email protected]02b0c342010-09-25 21:09:388578
8579 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8580 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288581 connection->Init(host_port_pair.ToString(), transport_params,
8582 LOWEST, &callback,
8583 session->transport_socket_pool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388584 EXPECT_EQ(OK, callback.WaitForResult());
8585 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038586
8587 HttpRequestInfo request;
8588 request.method = "GET";
8589 request.url = GURL("https://www.google.com/");
8590 request.load_flags = 0;
8591
8592 // This is the important line that marks this as a preconnect.
8593 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8594
8595 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8596
[email protected]749eefa82010-09-13 22:14:038597 int rv = trans->Start(&request, &callback, BoundNetLog());
8598 EXPECT_EQ(ERR_IO_PENDING, rv);
8599 EXPECT_EQ(OK, callback.WaitForResult());
8600}
8601
[email protected]73b8dd222010-11-11 19:55:248602// Given a net error, cause that error to be returned from the first Write()
8603// call and verify that the HttpTransaction fails with that error.
8604static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278605 net::HttpRequestInfo request_info;
8606 request_info.url = GURL("https://www.example.com/");
8607 request_info.method = "GET";
8608 request_info.load_flags = net::LOAD_NORMAL;
8609
[email protected]73b8dd222010-11-11 19:55:248610 SessionDependencies session_deps;
8611
8612 SSLSocketDataProvider ssl_data(async, OK);
8613 net::MockWrite data_writes[] = {
8614 net::MockWrite(async, error),
8615 };
8616 net::StaticSocketDataProvider data(NULL, 0,
8617 data_writes, arraysize(data_writes));
8618 session_deps.socket_factory.AddSocketDataProvider(&data);
8619 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8620
8621 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8622 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8623
[email protected]f1f3f0f82011-10-01 20:38:108624 TestOldCompletionCallback callback;
[email protected]73b8dd222010-11-11 19:55:248625 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8626 if (rv == net::ERR_IO_PENDING)
8627 rv = callback.WaitForResult();
8628 ASSERT_EQ(error, rv);
8629}
8630
8631TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8632 // Just check a grab bag of cert errors.
8633 static const int kErrors[] = {
8634 ERR_CERT_COMMON_NAME_INVALID,
8635 ERR_CERT_AUTHORITY_INVALID,
8636 ERR_CERT_DATE_INVALID,
8637 };
8638 for (size_t i = 0; i < arraysize(kErrors); i++) {
8639 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8640 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8641 }
8642}
8643
[email protected]bd0b6772011-01-11 19:59:308644// Ensure that a client certificate is removed from the SSL client auth
8645// cache when:
8646// 1) No proxy is involved.
8647// 2) TLS False Start is disabled.
8648// 3) The initial TLS handshake requests a client certificate.
8649// 4) The client supplies an invalid/unacceptable certificate.
8650TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278651 net::HttpRequestInfo request_info;
8652 request_info.url = GURL("https://www.example.com/");
8653 request_info.method = "GET";
8654 request_info.load_flags = net::LOAD_NORMAL;
8655
[email protected]bd0b6772011-01-11 19:59:308656 SessionDependencies session_deps;
8657
8658 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8659 cert_request->host_and_port = "www.example.com:443";
8660
8661 // [ssl_]data1 contains the data for the first SSL handshake. When a
8662 // CertificateRequest is received for the first time, the handshake will
8663 // be aborted to allow the caller to provide a certificate.
8664 SSLSocketDataProvider ssl_data1(true /* async */,
8665 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8666 ssl_data1.cert_request_info = cert_request.get();
8667 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8668 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8669 session_deps.socket_factory.AddSocketDataProvider(&data1);
8670
8671 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8672 // False Start is not being used, the result of the SSL handshake will be
8673 // returned as part of the SSLClientSocket::Connect() call. This test
8674 // matches the result of a server sending a handshake_failure alert,
8675 // rather than a Finished message, because it requires a client
8676 // certificate and none was supplied.
8677 SSLSocketDataProvider ssl_data2(true /* async */,
8678 net::ERR_SSL_PROTOCOL_ERROR);
8679 ssl_data2.cert_request_info = cert_request.get();
8680 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8681 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8682 session_deps.socket_factory.AddSocketDataProvider(&data2);
8683
8684 // [ssl_]data3 contains the data for the third SSL handshake. When a
8685 // connection to a server fails during an SSL handshake,
8686 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8687 // connection was attempted with TLSv1. This is transparent to the caller
8688 // of the HttpNetworkTransaction. Because this test failure is due to
8689 // requiring a client certificate, this fallback handshake should also
8690 // fail.
8691 SSLSocketDataProvider ssl_data3(true /* async */,
8692 net::ERR_SSL_PROTOCOL_ERROR);
8693 ssl_data3.cert_request_info = cert_request.get();
8694 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8695 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8696 session_deps.socket_factory.AddSocketDataProvider(&data3);
8697
8698 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8699 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8700
[email protected]bd0b6772011-01-11 19:59:308701 // Begin the SSL handshake with the peer. This consumes ssl_data1.
[email protected]f1f3f0f82011-10-01 20:38:108702 TestOldCompletionCallback callback;
[email protected]bd0b6772011-01-11 19:59:308703 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8704 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8705
8706 // Complete the SSL handshake, which should abort due to requiring a
8707 // client certificate.
8708 rv = callback.WaitForResult();
8709 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8710
8711 // Indicate that no certificate should be supplied. From the perspective
8712 // of SSLClientCertCache, NULL is just as meaningful as a real
8713 // certificate, so this is the same as supply a
8714 // legitimate-but-unacceptable certificate.
8715 rv = trans->RestartWithCertificate(NULL, &callback);
8716 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8717
8718 // Ensure the certificate was added to the client auth cache before
8719 // allowing the connection to continue restarting.
8720 scoped_refptr<X509Certificate> client_cert;
8721 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8722 &client_cert));
8723 ASSERT_EQ(NULL, client_cert.get());
8724
8725 // Restart the handshake. This will consume ssl_data2, which fails, and
8726 // then consume ssl_data3, which should also fail. The result code is
8727 // checked against what ssl_data3 should return.
8728 rv = callback.WaitForResult();
8729 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8730
8731 // Ensure that the client certificate is removed from the cache on a
8732 // handshake failure.
8733 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8734 &client_cert));
8735}
8736
8737// Ensure that a client certificate is removed from the SSL client auth
8738// cache when:
8739// 1) No proxy is involved.
8740// 2) TLS False Start is enabled.
8741// 3) The initial TLS handshake requests a client certificate.
8742// 4) The client supplies an invalid/unacceptable certificate.
8743TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278744 net::HttpRequestInfo request_info;
8745 request_info.url = GURL("https://www.example.com/");
8746 request_info.method = "GET";
8747 request_info.load_flags = net::LOAD_NORMAL;
8748
[email protected]bd0b6772011-01-11 19:59:308749 SessionDependencies session_deps;
8750
8751 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8752 cert_request->host_and_port = "www.example.com:443";
8753
8754 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8755 // return successfully after reading up to the peer's Certificate message.
8756 // This is to allow the caller to call SSLClientSocket::Write(), which can
8757 // enqueue application data to be sent in the same packet as the
8758 // ChangeCipherSpec and Finished messages.
8759 // The actual handshake will be finished when SSLClientSocket::Read() is
8760 // called, which expects to process the peer's ChangeCipherSpec and
8761 // Finished messages. If there was an error negotiating with the peer,
8762 // such as due to the peer requiring a client certificate when none was
8763 // supplied, the alert sent by the peer won't be processed until Read() is
8764 // called.
8765
8766 // Like the non-False Start case, when a client certificate is requested by
8767 // the peer, the handshake is aborted during the Connect() call.
8768 // [ssl_]data1 represents the initial SSL handshake with the peer.
8769 SSLSocketDataProvider ssl_data1(true /* async */,
8770 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8771 ssl_data1.cert_request_info = cert_request.get();
8772 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8773 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8774 session_deps.socket_factory.AddSocketDataProvider(&data1);
8775
8776 // When a client certificate is supplied, Connect() will not be aborted
8777 // when the peer requests the certificate. Instead, the handshake will
8778 // artificially succeed, allowing the caller to write the HTTP request to
8779 // the socket. The handshake messages are not processed until Read() is
8780 // called, which then detects that the handshake was aborted, due to the
8781 // peer sending a handshake_failure because it requires a client
8782 // certificate.
8783 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8784 ssl_data2.cert_request_info = cert_request.get();
8785 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8786 net::MockRead data2_reads[] = {
8787 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8788 };
8789 net::StaticSocketDataProvider data2(
8790 data2_reads, arraysize(data2_reads), NULL, 0);
8791 session_deps.socket_factory.AddSocketDataProvider(&data2);
8792
8793 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8794 // the data for the SSL handshake once the TLSv1 connection falls back to
8795 // SSLv3. It has the same behaviour as [ssl_]data2.
8796 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8797 ssl_data3.cert_request_info = cert_request.get();
8798 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8799 net::StaticSocketDataProvider data3(
8800 data2_reads, arraysize(data2_reads), NULL, 0);
8801 session_deps.socket_factory.AddSocketDataProvider(&data3);
8802
8803 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8804 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8805
[email protected]bd0b6772011-01-11 19:59:308806 // Begin the initial SSL handshake.
[email protected]f1f3f0f82011-10-01 20:38:108807 TestOldCompletionCallback callback;
[email protected]bd0b6772011-01-11 19:59:308808 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8809 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8810
8811 // Complete the SSL handshake, which should abort due to requiring a
8812 // client certificate.
8813 rv = callback.WaitForResult();
8814 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8815
8816 // Indicate that no certificate should be supplied. From the perspective
8817 // of SSLClientCertCache, NULL is just as meaningful as a real
8818 // certificate, so this is the same as supply a
8819 // legitimate-but-unacceptable certificate.
8820 rv = trans->RestartWithCertificate(NULL, &callback);
8821 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8822
8823 // Ensure the certificate was added to the client auth cache before
8824 // allowing the connection to continue restarting.
8825 scoped_refptr<X509Certificate> client_cert;
8826 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8827 &client_cert));
8828 ASSERT_EQ(NULL, client_cert.get());
8829
8830
8831 // Restart the handshake. This will consume ssl_data2, which fails, and
8832 // then consume ssl_data3, which should also fail. The result code is
8833 // checked against what ssl_data3 should return.
8834 rv = callback.WaitForResult();
8835 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8836
8837 // Ensure that the client certificate is removed from the cache on a
8838 // handshake failure.
8839 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8840 &client_cert));
8841}
8842
[email protected]8c405132011-01-11 22:03:188843// Ensure that a client certificate is removed from the SSL client auth
8844// cache when:
8845// 1) An HTTPS proxy is involved.
8846// 3) The HTTPS proxy requests a client certificate.
8847// 4) The client supplies an invalid/unacceptable certificate for the
8848// proxy.
8849// The test is repeated twice, first for connecting to an HTTPS endpoint,
8850// then for connecting to an HTTP endpoint.
8851TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8852 SessionDependencies session_deps(
8853 ProxyService::CreateFixed("https://proxy:70"));
8854 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8855 session_deps.net_log = log.bound().net_log();
8856
8857 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8858 cert_request->host_and_port = "proxy:70";
8859
8860 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8861 // [ssl_]data[1-3]. Rather than represending the endpoint
8862 // (www.example.com:443), they represent failures with the HTTPS proxy
8863 // (proxy:70).
8864 SSLSocketDataProvider ssl_data1(true /* async */,
8865 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8866 ssl_data1.cert_request_info = cert_request.get();
8867 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8868 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8869 session_deps.socket_factory.AddSocketDataProvider(&data1);
8870
8871 SSLSocketDataProvider ssl_data2(true /* async */,
8872 net::ERR_SSL_PROTOCOL_ERROR);
8873 ssl_data2.cert_request_info = cert_request.get();
8874 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8875 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8876 session_deps.socket_factory.AddSocketDataProvider(&data2);
8877
8878 SSLSocketDataProvider ssl_data3(true /* async */,
8879 net::ERR_SSL_PROTOCOL_ERROR);
8880 ssl_data3.cert_request_info = cert_request.get();
8881 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8882 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8883 session_deps.socket_factory.AddSocketDataProvider(&data3);
8884
8885 net::HttpRequestInfo requests[2];
8886 requests[0].url = GURL("https://www.example.com/");
8887 requests[0].method = "GET";
8888 requests[0].load_flags = net::LOAD_NORMAL;
8889
8890 requests[1].url = GURL("http://www.example.com/");
8891 requests[1].method = "GET";
8892 requests[1].load_flags = net::LOAD_NORMAL;
8893
8894 for (size_t i = 0; i < arraysize(requests); ++i) {
8895 session_deps.socket_factory.ResetNextMockIndexes();
8896 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8897 scoped_ptr<HttpNetworkTransaction> trans(
8898 new HttpNetworkTransaction(session));
8899
8900 // Begin the SSL handshake with the proxy.
[email protected]f1f3f0f82011-10-01 20:38:108901 TestOldCompletionCallback callback;
[email protected]8c405132011-01-11 22:03:188902 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8903 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8904
8905 // Complete the SSL handshake, which should abort due to requiring a
8906 // client certificate.
8907 rv = callback.WaitForResult();
8908 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8909
8910 // Indicate that no certificate should be supplied. From the perspective
8911 // of SSLClientCertCache, NULL is just as meaningful as a real
8912 // certificate, so this is the same as supply a
8913 // legitimate-but-unacceptable certificate.
8914 rv = trans->RestartWithCertificate(NULL, &callback);
8915 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8916
8917 // Ensure the certificate was added to the client auth cache before
8918 // allowing the connection to continue restarting.
8919 scoped_refptr<X509Certificate> client_cert;
8920 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8921 &client_cert));
8922 ASSERT_EQ(NULL, client_cert.get());
8923 // Ensure the certificate was NOT cached for the endpoint. This only
8924 // applies to HTTPS requests, but is fine to check for HTTP requests.
8925 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8926 &client_cert));
8927
8928 // Restart the handshake. This will consume ssl_data2, which fails, and
8929 // then consume ssl_data3, which should also fail. The result code is
8930 // checked against what ssl_data3 should return.
8931 rv = callback.WaitForResult();
8932 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8933
8934 // Now that the new handshake has failed, ensure that the client
8935 // certificate was removed from the client auth cache.
8936 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8937 &client_cert));
8938 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8939 &client_cert));
8940 }
8941}
8942
[email protected]5c288bc2011-07-26 15:12:058943void IPPoolingAddAlias(MockCachingHostResolver* host_resolver,
8944 SpdySessionPoolPeer* pool_peer,
8945 std::string host,
8946 int port,
8947 std::string iplist) {
8948 // Create a host resolver dependency that returns address |iplist| for
8949 // resolutions of |host|.
8950 host_resolver->rules()->AddIPLiteralRule(host, iplist, "");
[email protected]46da33be2011-07-19 21:58:048951
[email protected]5c288bc2011-07-26 15:12:058952 // Setup a HostPortProxyPair.
8953 HostPortPair host_port_pair(host, port);
8954 HostPortProxyPair pair = HostPortProxyPair(host_port_pair,
8955 ProxyServer::Direct());
[email protected]46da33be2011-07-19 21:58:048956
[email protected]5c288bc2011-07-26 15:12:058957 // Resolve the host and port.
8958 AddressList addresses;
8959 HostResolver::RequestInfo info(host_port_pair);
[email protected]f1f3f0f82011-10-01 20:38:108960 TestOldCompletionCallback callback;
[email protected]6e78dfb2011-07-28 21:34:478961 int rv = host_resolver->Resolve(info, &addresses, &callback, NULL,
8962 BoundNetLog());
8963 if (rv == ERR_IO_PENDING)
8964 rv = callback.WaitForResult();
8965 DCHECK_EQ(OK, rv);
[email protected]46da33be2011-07-19 21:58:048966
[email protected]5c288bc2011-07-26 15:12:058967 // Add the first address as an alias. It would have been better to call
8968 // MockClientSocket::GetPeerAddress but that returns 192.0.2.33 whereas
8969 // MockHostResolver returns 127.0.0.1 (MockHostResolverBase::Reset). So we use
8970 // the first address (127.0.0.1) returned by MockHostResolver as an alias for
8971 // the |pair|.
8972 const addrinfo* address = addresses.head();
8973 pool_peer->AddAlias(address, pair);
[email protected]46da33be2011-07-19 21:58:048974}
8975
[email protected]e3ceb682011-06-28 23:55:468976TEST_F(HttpNetworkTransactionTest, UseIPConnectionPooling) {
8977 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:348978 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:468979
8980 // Set up a special HttpNetworkSession with a MockCachingHostResolver.
8981 SessionDependencies session_deps;
8982 MockCachingHostResolver host_resolver;
8983 net::HttpNetworkSession::Params params;
8984 params.client_socket_factory = &session_deps.socket_factory;
8985 params.host_resolver = &host_resolver;
8986 params.cert_verifier = session_deps.cert_verifier.get();
8987 params.proxy_service = session_deps.proxy_service.get();
8988 params.ssl_config_service = session_deps.ssl_config_service;
8989 params.http_auth_handler_factory =
8990 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:538991 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:468992 params.net_log = session_deps.net_log;
8993 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:268994 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
8995 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:468996
8997 SSLSocketDataProvider ssl(true, OK);
8998 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8999 ssl.next_proto = "spdy/2";
9000 ssl.was_npn_negotiated = true;
9001 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9002
9003 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9004 "https://www.google.com", false, 1, LOWEST));
9005 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9006 "https://www.gmail.com", false, 3, LOWEST));
9007 MockWrite spdy_writes[] = {
9008 CreateMockWrite(*host1_req, 1),
9009 CreateMockWrite(*host2_req, 4),
9010 };
9011 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9012 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9013 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9014 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9015 MockRead spdy_reads[] = {
9016 CreateMockRead(*host1_resp, 2),
9017 CreateMockRead(*host1_resp_body, 3),
9018 CreateMockRead(*host2_resp, 5),
9019 CreateMockRead(*host2_resp_body, 6),
9020 MockRead(true, 0, 7),
9021 };
9022
9023 scoped_refptr<OrderedSocketData> spdy_data(
9024 new OrderedSocketData(
9025 spdy_reads, arraysize(spdy_reads),
9026 spdy_writes, arraysize(spdy_writes)));
9027 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
9028
[email protected]f1f3f0f82011-10-01 20:38:109029 TestOldCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469030 HttpRequestInfo request1;
9031 request1.method = "GET";
9032 request1.url = GURL("https://www.google.com/");
9033 request1.load_flags = 0;
9034 HttpNetworkTransaction trans1(session);
9035
9036 int rv = trans1.Start(&request1, &callback, BoundNetLog());
9037 EXPECT_EQ(ERR_IO_PENDING, rv);
9038 EXPECT_EQ(OK, callback.WaitForResult());
9039
9040 const HttpResponseInfo* response = trans1.GetResponseInfo();
9041 ASSERT_TRUE(response != NULL);
9042 ASSERT_TRUE(response->headers != NULL);
9043 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9044
9045 std::string response_data;
9046 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9047 EXPECT_EQ("hello!", response_data);
9048
9049 // Preload www.gmail.com into HostCache.
9050 HostPortPair host_port("www.gmail.com", 443);
9051 HostResolver::RequestInfo resolve_info(host_port);
9052 AddressList ignored;
[email protected]6e78dfb2011-07-28 21:34:479053 rv = host_resolver.Resolve(resolve_info, &ignored, &callback, NULL,
9054 BoundNetLog());
9055 EXPECT_EQ(ERR_IO_PENDING, rv);
9056 rv = callback.WaitForResult();
9057 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469058
[email protected]5c288bc2011-07-26 15:12:059059 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9060 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9061 // (www.google.com, 443).
9062 IPPoolingAddAlias(&host_resolver, &pool_peer, "www.google.com", 443,
9063 "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049064
[email protected]e3ceb682011-06-28 23:55:469065 HttpRequestInfo request2;
9066 request2.method = "GET";
9067 request2.url = GURL("https://www.gmail.com/");
9068 request2.load_flags = 0;
9069 HttpNetworkTransaction trans2(session);
9070
9071 rv = trans2.Start(&request2, &callback, BoundNetLog());
9072 EXPECT_EQ(ERR_IO_PENDING, rv);
9073 EXPECT_EQ(OK, callback.WaitForResult());
9074
9075 response = trans2.GetResponseInfo();
9076 ASSERT_TRUE(response != NULL);
9077 ASSERT_TRUE(response->headers != NULL);
9078 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9079 EXPECT_TRUE(response->was_fetched_via_spdy);
9080 EXPECT_TRUE(response->was_npn_negotiated);
9081 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9082 EXPECT_EQ("hello!", response_data);
9083
[email protected]5285d972011-10-18 18:56:349084 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469085 HttpStreamFactory::set_use_alternate_protocols(false);
9086}
9087
9088class OneTimeCachingHostResolver : public net::HostResolver {
9089 public:
9090 explicit OneTimeCachingHostResolver(const HostPortPair& host_port)
9091 : host_port_(host_port) {}
9092 virtual ~OneTimeCachingHostResolver() {}
9093
9094 RuleBasedHostResolverProc* rules() { return host_resolver_.rules(); }
9095
9096 // HostResolver methods:
9097 virtual int Resolve(const RequestInfo& info,
9098 AddressList* addresses,
[email protected]f1f3f0f82011-10-01 20:38:109099 OldCompletionCallback* callback,
[email protected]e3ceb682011-06-28 23:55:469100 RequestHandle* out_req,
[email protected]95a214c2011-08-04 21:50:409101 const BoundNetLog& net_log) OVERRIDE {
9102 return host_resolver_.Resolve(
[email protected]e3ceb682011-06-28 23:55:469103 info, addresses, callback, out_req, net_log);
[email protected]95a214c2011-08-04 21:50:409104 }
9105
9106 virtual int ResolveFromCache(const RequestInfo& info,
9107 AddressList* addresses,
9108 const BoundNetLog& net_log) OVERRIDE {
9109 int rv = host_resolver_.ResolveFromCache(info, addresses, net_log);
9110 if (rv == OK && info.host_port_pair().Equals(host_port_))
[email protected]e3ceb682011-06-28 23:55:469111 host_resolver_.Reset(NULL);
[email protected]e3ceb682011-06-28 23:55:469112 return rv;
9113 }
9114
[email protected]95a214c2011-08-04 21:50:409115 virtual void CancelRequest(RequestHandle req) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469116 host_resolver_.CancelRequest(req);
9117 }
9118
[email protected]95a214c2011-08-04 21:50:409119 virtual void AddObserver(Observer* observer) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469120 return host_resolver_.AddObserver(observer);
9121 }
9122
[email protected]3912662a32011-10-04 00:51:119123 virtual void RemoveObserver(Observer* observer) OVERRIDE {
[email protected]e3ceb682011-06-28 23:55:469124 return host_resolver_.RemoveObserver(observer);
9125 }
9126
[email protected]46da33be2011-07-19 21:58:049127 MockCachingHostResolver* GetMockHostResolver() {
9128 return &host_resolver_;
9129 }
9130
[email protected]e3ceb682011-06-28 23:55:469131 private:
9132 MockCachingHostResolver host_resolver_;
9133 const HostPortPair host_port_;
9134};
9135
9136TEST_F(HttpNetworkTransactionTest,
9137 UseIPConnectionPoolingWithHostCacheExpiration) {
9138 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]5285d972011-10-18 18:56:349139 HttpStreamFactory::set_next_protos(SpdyNextProtos());
[email protected]e3ceb682011-06-28 23:55:469140
9141 // Set up a special HttpNetworkSession with a OneTimeCachingHostResolver.
9142 SessionDependencies session_deps;
9143 OneTimeCachingHostResolver host_resolver(HostPortPair("www.gmail.com", 443));
9144 net::HttpNetworkSession::Params params;
9145 params.client_socket_factory = &session_deps.socket_factory;
9146 params.host_resolver = &host_resolver;
9147 params.cert_verifier = session_deps.cert_verifier.get();
9148 params.proxy_service = session_deps.proxy_service.get();
9149 params.ssl_config_service = session_deps.ssl_config_service;
9150 params.http_auth_handler_factory =
9151 session_deps.http_auth_handler_factory.get();
[email protected]17291a022011-10-10 07:32:539152 params.http_server_properties = &session_deps.http_server_properties;
[email protected]e3ceb682011-06-28 23:55:469153 params.net_log = session_deps.net_log;
9154 scoped_refptr<HttpNetworkSession> session(new HttpNetworkSession(params));
[email protected]b9ec6882011-07-01 07:40:269155 SpdySessionPoolPeer pool_peer(session->spdy_session_pool());
9156 pool_peer.DisableDomainAuthenticationVerification();
[email protected]e3ceb682011-06-28 23:55:469157
9158 SSLSocketDataProvider ssl(true, OK);
9159 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
9160 ssl.next_proto = "spdy/2";
9161 ssl.was_npn_negotiated = true;
9162 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
9163
9164 scoped_ptr<spdy::SpdyFrame> host1_req(ConstructSpdyGet(
9165 "https://www.google.com", false, 1, LOWEST));
9166 scoped_ptr<spdy::SpdyFrame> host2_req(ConstructSpdyGet(
9167 "https://www.gmail.com", false, 3, LOWEST));
9168 MockWrite spdy_writes[] = {
9169 CreateMockWrite(*host1_req, 1),
9170 CreateMockWrite(*host2_req, 4),
9171 };
9172 scoped_ptr<spdy::SpdyFrame> host1_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
9173 scoped_ptr<spdy::SpdyFrame> host1_resp_body(ConstructSpdyBodyFrame(1, true));
9174 scoped_ptr<spdy::SpdyFrame> host2_resp(ConstructSpdyGetSynReply(NULL, 0, 3));
9175 scoped_ptr<spdy::SpdyFrame> host2_resp_body(ConstructSpdyBodyFrame(3, true));
9176 MockRead spdy_reads[] = {
9177 CreateMockRead(*host1_resp, 2),
9178 CreateMockRead(*host1_resp_body, 3),
9179 CreateMockRead(*host2_resp, 5),
9180 CreateMockRead(*host2_resp_body, 6),
9181 MockRead(true, 0, 7),
9182 };
9183
9184 scoped_refptr<OrderedSocketData> spdy_data(
9185 new OrderedSocketData(
9186 spdy_reads, arraysize(spdy_reads),
9187 spdy_writes, arraysize(spdy_writes)));
9188 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
9189
[email protected]f1f3f0f82011-10-01 20:38:109190 TestOldCompletionCallback callback;
[email protected]e3ceb682011-06-28 23:55:469191 HttpRequestInfo request1;
9192 request1.method = "GET";
9193 request1.url = GURL("https://www.google.com/");
9194 request1.load_flags = 0;
9195 HttpNetworkTransaction trans1(session);
9196
9197 int rv = trans1.Start(&request1, &callback, BoundNetLog());
9198 EXPECT_EQ(ERR_IO_PENDING, rv);
9199 EXPECT_EQ(OK, callback.WaitForResult());
9200
9201 const HttpResponseInfo* response = trans1.GetResponseInfo();
9202 ASSERT_TRUE(response != NULL);
9203 ASSERT_TRUE(response->headers != NULL);
9204 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9205
9206 std::string response_data;
9207 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
9208 EXPECT_EQ("hello!", response_data);
9209
9210 // Preload cache entries into HostCache.
9211 HostResolver::RequestInfo resolve_info(HostPortPair("www.gmail.com", 443));
9212 AddressList ignored;
[email protected]6e78dfb2011-07-28 21:34:479213 rv = host_resolver.Resolve(resolve_info, &ignored, &callback, NULL,
9214 BoundNetLog());
9215 EXPECT_EQ(ERR_IO_PENDING, rv);
9216 rv = callback.WaitForResult();
9217 EXPECT_EQ(OK, rv);
[email protected]e3ceb682011-06-28 23:55:469218
9219 HttpRequestInfo request2;
9220 request2.method = "GET";
9221 request2.url = GURL("https://www.gmail.com/");
9222 request2.load_flags = 0;
9223 HttpNetworkTransaction trans2(session);
9224
[email protected]5c288bc2011-07-26 15:12:059225 // MockHostResolver returns 127.0.0.1, port 443 for https://www.google.com/
9226 // and https://www.gmail.com/. Add 127.0.0.1 as alias for host_port_pair:
9227 // (www.google.com, 443).
9228 IPPoolingAddAlias(host_resolver.GetMockHostResolver(), &pool_peer,
9229 "www.google.com", 443, "127.0.0.1");
[email protected]46da33be2011-07-19 21:58:049230
[email protected]e3ceb682011-06-28 23:55:469231 rv = trans2.Start(&request2, &callback, BoundNetLog());
9232 EXPECT_EQ(ERR_IO_PENDING, rv);
9233 EXPECT_EQ(OK, callback.WaitForResult());
9234
9235 response = trans2.GetResponseInfo();
9236 ASSERT_TRUE(response != NULL);
9237 ASSERT_TRUE(response->headers != NULL);
9238 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
9239 EXPECT_TRUE(response->was_fetched_via_spdy);
9240 EXPECT_TRUE(response->was_npn_negotiated);
9241 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
9242 EXPECT_EQ("hello!", response_data);
9243
[email protected]5285d972011-10-18 18:56:349244 HttpStreamFactory::set_next_protos(std::vector<std::string>());
[email protected]e3ceb682011-06-28 23:55:469245 HttpStreamFactory::set_use_alternate_protocols(false);
9246}
9247
[email protected]89ceba9a2009-03-21 03:46:069248} // namespace net