blob: 45b3d793a6d3e7ba12668da5d11f296c767d6dfe [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]95d88ffe2010-02-04 21:25:338#include <vector>
[email protected]77848d12008-11-14 00:00:229
[email protected]2d731a32010-04-29 01:04:0610#include "base/basictypes.h"
[email protected]68bf9152008-09-25 19:47:3011#include "base/compiler_specific.h"
[email protected]95d88ffe2010-02-04 21:25:3312#include "base/file_path.h"
13#include "base/file_util.h"
[email protected]3b63f8f42011-03-28 01:54:1514#include "base/memory/scoped_ptr.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]277d5942010-08-11 21:02:3516#include "net/base/auth.h"
[email protected]169d0012010-05-10 23:20:1217#include "net/base/capturing_net_log.h"
[email protected]bacff652009-03-31 17:50:3318#include "net/base/completion_callback.h"
[email protected]b59ff372009-07-15 22:04:3219#include "net/base/mock_host_resolver.h"
[email protected]169d0012010-05-10 23:20:1220#include "net/base/net_log.h"
21#include "net/base/net_log_unittest.h"
[email protected]ac790b42009-12-02 04:31:3122#include "net/base/request_priority.h"
[email protected]bd0b6772011-01-11 19:59:3023#include "net/base/ssl_cert_request_info.h"
[email protected]db36938c2009-08-19 21:48:4224#include "net/base/ssl_config_service_defaults.h"
[email protected]bacff652009-03-31 17:50:3325#include "net/base/ssl_info.h"
initial.commit586acc5fe2008-07-26 22:42:5226#include "net/base/test_completion_callback.h"
27#include "net/base/upload_data.h"
[email protected]3c32c5f2010-05-18 15:18:1228#include "net/http/http_auth_handler_digest.h"
[email protected]3fd9dae2010-06-21 11:39:0029#include "net/http/http_auth_handler_mock.h"
[email protected]385a4672009-03-11 22:21:2930#include "net/http/http_auth_handler_ntlm.h"
[email protected]0877e3d2009-10-17 22:29:5731#include "net/http/http_basic_stream.h"
[email protected]3deb9a52010-11-11 00:24:4032#include "net/http/http_net_log_params.h"
initial.commit586acc5fe2008-07-26 22:42:5233#include "net/http/http_network_session.h"
[email protected]87bfa3f2010-09-30 14:54:5634#include "net/http/http_network_session_peer.h"
[email protected]0877e3d2009-10-17 22:29:5735#include "net/http/http_stream.h"
[email protected]8e6441ca2010-08-19 05:56:3836#include "net/http/http_stream_factory.h"
initial.commit586acc5fe2008-07-26 22:42:5237#include "net/http/http_transaction_unittest.h"
[email protected]51fff29d2008-12-19 22:17:5338#include "net/proxy/proxy_config_service_fixed.h"
[email protected]631f1322010-04-30 17:59:1139#include "net/proxy/proxy_resolver.h"
40#include "net/proxy/proxy_service.h"
[email protected]f7984fc62009-06-22 23:26:4441#include "net/socket/client_socket_factory.h"
42#include "net/socket/socket_test_util.h"
43#include "net/socket/ssl_client_socket.h"
[email protected]2ff8b312010-04-26 22:20:5444#include "net/spdy/spdy_framer.h"
45#include "net/spdy/spdy_session.h"
46#include "net/spdy/spdy_session_pool.h"
47#include "net/spdy/spdy_test_util.h"
initial.commit586acc5fe2008-07-26 22:42:5248#include "testing/gtest/include/gtest/gtest.h"
[email protected]23887f04f2008-12-02 19:20:1549#include "testing/platform_test.h"
initial.commit586acc5fe2008-07-26 22:42:5250
51//-----------------------------------------------------------------------------
52
[email protected]13c8a092010-07-29 06:15:4453namespace {
54
55const string16 kBar(ASCIIToUTF16("bar"));
56const string16 kBar2(ASCIIToUTF16("bar2"));
57const string16 kBar3(ASCIIToUTF16("bar3"));
58const string16 kBaz(ASCIIToUTF16("baz"));
59const string16 kFirst(ASCIIToUTF16("first"));
60const string16 kFoo(ASCIIToUTF16("foo"));
61const string16 kFoo2(ASCIIToUTF16("foo2"));
62const string16 kFoo3(ASCIIToUTF16("foo3"));
63const string16 kFou(ASCIIToUTF16("fou"));
64const string16 kSecond(ASCIIToUTF16("second"));
65const string16 kTestingNTLM(ASCIIToUTF16("testing-ntlm"));
66const string16 kWrongPassword(ASCIIToUTF16("wrongpassword"));
67
68} // namespace
69
[email protected]89ceba9a2009-03-21 03:46:0670namespace net {
71
[email protected]e44de5d2009-06-05 20:12:4572// Helper to manage the lifetimes of the dependencies for a
73// HttpNetworkTransaction.
[email protected]ac039522010-06-15 16:39:4474struct SessionDependencies {
[email protected]228ff742009-06-05 01:19:5975 // Default set of dependencies -- "null" proxy service.
[email protected]db36938c2009-08-19 21:48:4276 SessionDependencies()
77 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1578 cert_verifier(new CertVerifier),
[email protected]ebeefff32010-09-15 05:10:0279 proxy_service(ProxyService::CreateDirect()),
[email protected]d1eda932009-11-04 01:03:1080 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0881 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5482 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5483 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5984
85 // Custom proxy service dependency.
[email protected]e44de5d2009-06-05 20:12:4586 explicit SessionDependencies(ProxyService* proxy_service)
[email protected]db36938c2009-08-19 21:48:4287 : host_resolver(new MockHostResolver),
[email protected]822581d2010-12-16 17:27:1588 cert_verifier(new CertVerifier),
[email protected]db36938c2009-08-19 21:48:4289 proxy_service(proxy_service),
[email protected]d1eda932009-11-04 01:03:1090 ssl_config_service(new SSLConfigServiceDefaults),
[email protected]f660e4b2010-09-29 14:20:0891 http_auth_handler_factory(
[email protected]73c45322010-10-01 23:57:5492 HttpAuthHandlerFactory::CreateDefault(host_resolver.get())),
[email protected]a7ea8832010-07-12 17:54:5493 net_log(NULL) {}
[email protected]228ff742009-06-05 01:19:5994
[email protected]73c45322010-10-01 23:57:5495 scoped_ptr<MockHostResolverBase> host_resolver;
[email protected]822581d2010-12-16 17:27:1596 scoped_ptr<CertVerifier> cert_verifier;
[email protected]6104ea5d2011-04-27 21:37:1297 scoped_ptr<ProxyService> proxy_service;
[email protected]db36938c2009-08-19 21:48:4298 scoped_refptr<SSLConfigService> ssl_config_service;
[email protected]228ff742009-06-05 01:19:5999 MockClientSocketFactory socket_factory;
[email protected]fa55e192010-02-15 14:25:50100 scoped_ptr<HttpAuthHandlerFactory> http_auth_handler_factory;
[email protected]a7ea8832010-07-12 17:54:54101 NetLog* net_log;
[email protected]228ff742009-06-05 01:19:59102};
103
[email protected]228ff742009-06-05 01:19:59104HttpNetworkSession* CreateSession(SessionDependencies* session_deps) {
[email protected]9e1bdd32011-02-03 21:48:34105 net::HttpNetworkSession::Params params;
106 params.client_socket_factory = &session_deps->socket_factory;
107 params.host_resolver = session_deps->host_resolver.get();
108 params.cert_verifier = session_deps->cert_verifier.get();
[email protected]6104ea5d2011-04-27 21:37:12109 params.proxy_service = session_deps->proxy_service.get();
[email protected]9e1bdd32011-02-03 21:48:34110 params.ssl_config_service = session_deps->ssl_config_service;
111 params.http_auth_handler_factory =
112 session_deps->http_auth_handler_factory.get();
113 params.net_log = session_deps->net_log;
114 return new HttpNetworkSession(params);
[email protected]e8d536192008-10-17 22:21:14115}
116
[email protected]89836e22008-09-25 20:33:42117class HttpNetworkTransactionTest : public PlatformTest {
initial.commit586acc5fe2008-07-26 22:42:52118 public:
[email protected]2ff8b312010-04-26 22:20:54119 virtual void SetUp() {
[email protected]0b0bf032010-09-21 18:08:50120 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
121 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54122 spdy::SpdyFramer::set_enable_compression_default(false);
123 }
124
[email protected]0e75a732008-10-16 20:36:09125 virtual void TearDown() {
[email protected]0b0bf032010-09-21 18:08:50126 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
127 MessageLoop::current()->RunAllPending();
[email protected]2ff8b312010-04-26 22:20:54128 spdy::SpdyFramer::set_enable_compression_default(true);
[email protected]0e75a732008-10-16 20:36:09129 // Empty the current queue.
130 MessageLoop::current()->RunAllPending();
131 PlatformTest::TearDown();
[email protected]0b0bf032010-09-21 18:08:50132 NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
133 MessageLoop::current()->RunAllPending();
[email protected]0e75a732008-10-16 20:36:09134 }
135
[email protected]3d2a59b2008-09-26 19:44:25136 protected:
137 void KeepAliveConnectionResendRequestTest(const MockRead& read_failure);
initial.commit586acc5fe2008-07-26 22:42:52138
[email protected]ff007e162009-05-23 09:13:15139 struct SimpleGetHelperResult {
140 int rv;
141 std::string status_line;
142 std::string response_data;
143 };
initial.commit586acc5fe2008-07-26 22:42:52144
[email protected]31a2bfe2010-02-09 08:03:39145 SimpleGetHelperResult SimpleGetHelper(MockRead data_reads[],
146 size_t reads_count) {
[email protected]ff007e162009-05-23 09:13:15147 SimpleGetHelperResult out;
initial.commit586acc5fe2008-07-26 22:42:52148
[email protected]ff007e162009-05-23 09:13:15149 HttpRequestInfo request;
150 request.method = "GET";
151 request.url = GURL("http://www.google.com/");
152 request.load_flags = 0;
initial.commit586acc5fe2008-07-26 22:42:52153
[email protected]cb9bf6ca2011-01-28 13:15:27154 SessionDependencies session_deps;
155 scoped_ptr<HttpTransaction> trans(
156 new HttpNetworkTransaction(CreateSession(&session_deps)));
157
[email protected]31a2bfe2010-02-09 08:03:39158 StaticSocketDataProvider data(data_reads, reads_count, NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59159 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52160
[email protected]ff007e162009-05-23 09:13:15161 TestCompletionCallback callback;
initial.commit586acc5fe2008-07-26 22:42:52162
[email protected]169d0012010-05-10 23:20:12163 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
[email protected]3deb9a52010-11-11 00:24:40164 EXPECT_TRUE(log.bound().IsLoggingAllEvents());
[email protected]169d0012010-05-10 23:20:12165 int rv = trans->Start(&request, &callback, log.bound());
[email protected]ff007e162009-05-23 09:13:15166 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52167
[email protected]ff007e162009-05-23 09:13:15168 out.rv = callback.WaitForResult();
169 if (out.rv != OK)
170 return out;
171
172 const HttpResponseInfo* response = trans->GetResponseInfo();
173 EXPECT_TRUE(response != NULL);
174
175 EXPECT_TRUE(response->headers != NULL);
176 out.status_line = response->headers->GetStatusLine();
177
[email protected]6d81b482011-02-22 19:47:19178 EXPECT_EQ("192.0.2.33", response->socket_address.host());
179 EXPECT_EQ(0, response->socket_address.port());
180
[email protected]ff007e162009-05-23 09:13:15181 rv = ReadTransaction(trans.get(), &out.response_data);
182 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:40183
184 net::CapturingNetLog::EntryList entries;
185 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:39186 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40187 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_REQUEST_HEADERS,
[email protected]169d0012010-05-10 23:20:12188 NetLog::PHASE_NONE);
[email protected]dbb83db2010-05-11 18:13:39189 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:40190 entries, pos,
[email protected]dbb83db2010-05-11 18:13:39191 NetLog::TYPE_HTTP_TRANSACTION_READ_RESPONSE_HEADERS,
192 NetLog::PHASE_NONE);
[email protected]ff007e162009-05-23 09:13:15193
[email protected]b2fcd0e2010-12-01 15:19:40194 CapturingNetLog::Entry entry = entries[pos];
[email protected]3deb9a52010-11-11 00:24:40195 NetLogHttpRequestParameter* request_params =
196 static_cast<NetLogHttpRequestParameter*>(entry.extra_parameters.get());
197 EXPECT_EQ("GET / HTTP/1.1\r\n", request_params->GetLine());
198 EXPECT_EQ("Host: www.google.com\r\n"
199 "Connection: keep-alive\r\n\r\n",
200 request_params->GetHeaders().ToString());
201
[email protected]aecfbf22008-10-16 02:02:47202 return out;
[email protected]ff007e162009-05-23 09:13:15203 }
initial.commit586acc5fe2008-07-26 22:42:52204
[email protected]ff007e162009-05-23 09:13:15205 void ConnectStatusHelperWithExpectedStatus(const MockRead& status,
206 int expected_status);
initial.commit586acc5fe2008-07-26 22:42:52207
[email protected]ff007e162009-05-23 09:13:15208 void ConnectStatusHelper(const MockRead& status);
[email protected]ff007e162009-05-23 09:13:15209};
[email protected]231d5a32008-09-13 00:45:27210
[email protected]15a5ccf82008-10-23 19:57:43211// Fill |str| with a long header list that consumes >= |size| bytes.
212void FillLargeHeadersString(std::string* str, int size) {
[email protected]4ddaf2502008-10-23 18:26:19213 const char* row =
214 "SomeHeaderName: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\r\n";
215 const int sizeof_row = strlen(row);
216 const int num_rows = static_cast<int>(
217 ceil(static_cast<float>(size) / sizeof_row));
218 const int sizeof_data = num_rows * sizeof_row;
219 DCHECK(sizeof_data >= size);
[email protected]15a5ccf82008-10-23 19:57:43220 str->reserve(sizeof_data);
[email protected]372d34a2008-11-05 21:30:51221
[email protected]4ddaf2502008-10-23 18:26:19222 for (int i = 0; i < num_rows; ++i)
[email protected]15a5ccf82008-10-23 19:57:43223 str->append(row, sizeof_row);
[email protected]4ddaf2502008-10-23 18:26:19224}
225
[email protected]385a4672009-03-11 22:21:29226// Alternative functions that eliminate randomness and dependency on the local
227// host name so that the generated NTLM messages are reproducible.
[email protected]fe2bc6a2009-03-23 16:52:20228void MockGenerateRandom1(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29229 static const uint8 bytes[] = {
230 0x55, 0x29, 0x66, 0x26, 0x6b, 0x9c, 0x73, 0x54
231 };
232 static size_t current_byte = 0;
233 for (size_t i = 0; i < n; ++i) {
234 output[i] = bytes[current_byte++];
235 current_byte %= arraysize(bytes);
236 }
237}
238
[email protected]fe2bc6a2009-03-23 16:52:20239void MockGenerateRandom2(uint8* output, size_t n) {
[email protected]385a4672009-03-11 22:21:29240 static const uint8 bytes[] = {
241 0x96, 0x79, 0x85, 0xe7, 0x49, 0x93, 0x70, 0xa1,
242 0x4e, 0xe7, 0x87, 0x45, 0x31, 0x5b, 0xd3, 0x1f
243 };
244 static size_t current_byte = 0;
245 for (size_t i = 0; i < n; ++i) {
246 output[i] = bytes[current_byte++];
247 current_byte %= arraysize(bytes);
248 }
249}
250
[email protected]fe2bc6a2009-03-23 16:52:20251std::string MockGetHostName() {
252 return "WTC-WIN7";
[email protected]385a4672009-03-11 22:21:29253}
254
[email protected]e60e47a2010-07-14 03:37:18255template<typename ParentPool>
256class CaptureGroupNameSocketPool : public ParentPool {
[email protected]04e5be32009-06-26 20:00:31257 public:
[email protected]9e1bdd32011-02-03 21:48:34258 CaptureGroupNameSocketPool(HostResolver* host_resolver,
259 CertVerifier* cert_verifier);
[email protected]e60e47a2010-07-14 03:37:18260
[email protected]d80a4322009-08-14 07:07:49261 const std::string last_group_name_received() const {
262 return last_group_name_;
263 }
264
[email protected]684970b2009-08-14 04:54:46265 virtual int RequestSocket(const std::string& group_name,
[email protected]d80a4322009-08-14 07:07:49266 const void* socket_params,
[email protected]ac790b42009-12-02 04:31:31267 RequestPriority priority,
[email protected]04e5be32009-06-26 20:00:31268 ClientSocketHandle* handle,
[email protected]684970b2009-08-14 04:54:46269 CompletionCallback* callback,
[email protected]9e743cd2010-03-16 07:03:53270 const BoundNetLog& net_log) {
[email protected]04e5be32009-06-26 20:00:31271 last_group_name_ = group_name;
272 return ERR_IO_PENDING;
273 }
[email protected]04e5be32009-06-26 20:00:31274 virtual void CancelRequest(const std::string& group_name,
[email protected]05ea9ff2010-07-15 19:08:21275 ClientSocketHandle* handle) {}
[email protected]04e5be32009-06-26 20:00:31276 virtual void ReleaseSocket(const std::string& group_name,
[email protected]3268023f2011-05-05 00:08:10277 StreamSocket* socket,
[email protected]9f95c692011-02-11 19:20:19278 int id) {}
[email protected]04e5be32009-06-26 20:00:31279 virtual void CloseIdleSockets() {}
[email protected]04e5be32009-06-26 20:00:31280 virtual int IdleSocketCount() const {
281 return 0;
282 }
283 virtual int IdleSocketCountInGroup(const std::string& group_name) const {
284 return 0;
285 }
286 virtual LoadState GetLoadState(const std::string& group_name,
287 const ClientSocketHandle* handle) const {
288 return LOAD_STATE_IDLE;
289 }
[email protected]a796bcec2010-03-22 17:17:26290 virtual base::TimeDelta ConnectionTimeout() const {
291 return base::TimeDelta();
292 }
[email protected]d80a4322009-08-14 07:07:49293
294 private:
[email protected]04e5be32009-06-26 20:00:31295 std::string last_group_name_;
296};
297
[email protected]ab739042011-04-07 15:22:28298typedef CaptureGroupNameSocketPool<TransportClientSocketPool>
299CaptureGroupNameTransportSocketPool;
[email protected]e772db3f2010-07-12 18:11:13300typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
301CaptureGroupNameHttpProxySocketPool;
[email protected]2d731a32010-04-29 01:04:06302typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
[email protected]2227c692010-05-04 15:36:11303CaptureGroupNameSOCKSSocketPool;
[email protected]e60e47a2010-07-14 03:37:18304typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
305CaptureGroupNameSSLSocketPool;
306
307template<typename ParentPool>
308CaptureGroupNameSocketPool<ParentPool>::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34309 HostResolver* host_resolver,
310 CertVerifier* /* cert_verifier */)
311 : ParentPool(0, 0, NULL, host_resolver, NULL, NULL) {}
[email protected]e60e47a2010-07-14 03:37:18312
313template<>
[email protected]2df19bb2010-08-25 20:13:46314CaptureGroupNameHttpProxySocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34315 HostResolver* host_resolver,
316 CertVerifier* /* cert_verifier */)
317 : HttpProxyClientSocketPool(0, 0, NULL, host_resolver, NULL, NULL, NULL) {}
[email protected]2df19bb2010-08-25 20:13:46318
319template<>
[email protected]e60e47a2010-07-14 03:37:18320CaptureGroupNameSSLSocketPool::CaptureGroupNameSocketPool(
[email protected]9e1bdd32011-02-03 21:48:34321 HostResolver* host_resolver,
322 CertVerifier* cert_verifier)
323 : SSLClientSocketPool(0, 0, NULL, host_resolver, cert_verifier, NULL, NULL,
[email protected]345c613b2010-11-22 19:33:18324 NULL, NULL, NULL, NULL, NULL, NULL, NULL) {}
[email protected]2227c692010-05-04 15:36:11325
[email protected]231d5a32008-09-13 00:45:27326//-----------------------------------------------------------------------------
327
[email protected]dae22c52010-07-30 02:16:35328// This is the expected list of advertised protocols from the browser's NPN
329// list.
330static const char kExpectedNPNString[] = "\x08http/1.1\x06spdy/2";
331
332// This is the expected return from a current server advertising SPDY.
333static const char kAlternateProtocolHttpHeader[] =
334 "Alternate-Protocol: 443:npn-spdy/2\r\n\r\n";
335
[email protected]231d5a32008-09-13 00:45:27336TEST_F(HttpNetworkTransactionTest, Basic) {
[email protected]228ff742009-06-05 01:19:59337 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:40338 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:43339 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]231d5a32008-09-13 00:45:27340}
341
342TEST_F(HttpNetworkTransactionTest, SimpleGET) {
343 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35344 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
345 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42346 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27347 };
[email protected]31a2bfe2010-02-09 08:03:39348 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
349 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42350 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27351 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
352 EXPECT_EQ("hello world", out.response_data);
353}
354
355// Response with no status line.
356TEST_F(HttpNetworkTransactionTest, SimpleGETNoHeaders) {
357 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35358 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42359 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27360 };
[email protected]31a2bfe2010-02-09 08:03:39361 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
362 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42363 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27364 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
365 EXPECT_EQ("hello world", out.response_data);
366}
367
368// Allow up to 4 bytes of junk to precede status line.
369TEST_F(HttpNetworkTransactionTest, StatusLineJunk2Bytes) {
370 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35371 MockRead("xxxHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42372 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27373 };
[email protected]31a2bfe2010-02-09 08:03:39374 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
375 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42376 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27377 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
378 EXPECT_EQ("DATA", out.response_data);
379}
380
381// Allow up to 4 bytes of junk to precede status line.
382TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes) {
383 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35384 MockRead("\n\nQJHTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42385 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27386 };
[email protected]31a2bfe2010-02-09 08:03:39387 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
388 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42389 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27390 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
391 EXPECT_EQ("DATA", out.response_data);
392}
393
394// Beyond 4 bytes of slop and it should fail to find a status line.
395TEST_F(HttpNetworkTransactionTest, StatusLineJunk5Bytes) {
396 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35397 MockRead("xxxxxHTTP/1.1 404 Not Found\nServer: blah"),
[email protected]1c773ea12009-04-28 19:58:42398 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27399 };
[email protected]31a2bfe2010-02-09 08:03:39400 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
401 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42402 EXPECT_EQ(OK, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25403 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
404 EXPECT_EQ("xxxxxHTTP/1.1 404 Not Found\nServer: blah", out.response_data);
[email protected]231d5a32008-09-13 00:45:27405}
406
407// Same as StatusLineJunk4Bytes, except the read chunks are smaller.
408TEST_F(HttpNetworkTransactionTest, StatusLineJunk4Bytes_Slow) {
409 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35410 MockRead("\n"),
411 MockRead("\n"),
412 MockRead("Q"),
413 MockRead("J"),
414 MockRead("HTTP/1.0 404 Not Found\nServer: blah\n\nDATA"),
[email protected]1c773ea12009-04-28 19:58:42415 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27416 };
[email protected]31a2bfe2010-02-09 08:03:39417 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
418 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42419 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27420 EXPECT_EQ("HTTP/1.0 404 Not Found", out.status_line);
421 EXPECT_EQ("DATA", out.response_data);
422}
423
424// Close the connection before enough bytes to have a status line.
425TEST_F(HttpNetworkTransactionTest, StatusLinePartial) {
426 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35427 MockRead("HTT"),
[email protected]1c773ea12009-04-28 19:58:42428 MockRead(false, OK),
[email protected]231d5a32008-09-13 00:45:27429 };
[email protected]31a2bfe2010-02-09 08:03:39430 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
431 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42432 EXPECT_EQ(OK, out.rv);
[email protected]231d5a32008-09-13 00:45:27433 EXPECT_EQ("HTTP/0.9 200 OK", out.status_line);
434 EXPECT_EQ("HTT", out.response_data);
initial.commit586acc5fe2008-07-26 22:42:52435}
436
[email protected]f9d44aa2008-09-23 23:57:17437// Simulate a 204 response, lacking a Content-Length header, sent over a
438// persistent connection. The response should still terminate since a 204
439// cannot have a response body.
440TEST_F(HttpNetworkTransactionTest, StopsReading204) {
441 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35442 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
443 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:42444 MockRead(false, OK),
[email protected]f9d44aa2008-09-23 23:57:17445 };
[email protected]31a2bfe2010-02-09 08:03:39446 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
447 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42448 EXPECT_EQ(OK, out.rv);
[email protected]f9d44aa2008-09-23 23:57:17449 EXPECT_EQ("HTTP/1.1 204 No Content", out.status_line);
450 EXPECT_EQ("", out.response_data);
451}
452
[email protected]0877e3d2009-10-17 22:29:57453// A simple request using chunked encoding with some extra data after.
454// (Like might be seen in a pipelined response.)
455TEST_F(HttpNetworkTransactionTest, ChunkedEncoding) {
456 MockRead data_reads[] = {
457 MockRead("HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n"),
458 MockRead("5\r\nHello\r\n"),
459 MockRead("1\r\n"),
460 MockRead(" \r\n"),
461 MockRead("5\r\nworld\r\n"),
462 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
463 MockRead(false, OK),
464 };
[email protected]31a2bfe2010-02-09 08:03:39465 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
466 arraysize(data_reads));
[email protected]0877e3d2009-10-17 22:29:57467 EXPECT_EQ(OK, out.rv);
468 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
469 EXPECT_EQ("Hello world", out.response_data);
470}
471
[email protected]9fe44f52010-09-23 18:36:00472// Next tests deal with http://crbug.com/56344.
473
474TEST_F(HttpNetworkTransactionTest,
475 MultipleContentLengthHeadersNoTransferEncoding) {
476 MockRead data_reads[] = {
477 MockRead("HTTP/1.1 200 OK\r\n"),
478 MockRead("Content-Length: 10\r\n"),
479 MockRead("Content-Length: 5\r\n\r\n"),
480 };
481 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
482 arraysize(data_reads));
483 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
484}
485
486TEST_F(HttpNetworkTransactionTest,
[email protected]44b52042010-10-29 22:48:04487 DuplicateContentLengthHeadersNoTransferEncoding) {
488 MockRead data_reads[] = {
489 MockRead("HTTP/1.1 200 OK\r\n"),
490 MockRead("Content-Length: 5\r\n"),
491 MockRead("Content-Length: 5\r\n\r\n"),
492 MockRead("Hello"),
493 };
494 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
495 arraysize(data_reads));
496 EXPECT_EQ(OK, out.rv);
497 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
498 EXPECT_EQ("Hello", out.response_data);
499}
500
501TEST_F(HttpNetworkTransactionTest,
502 ComplexContentLengthHeadersNoTransferEncoding) {
503 // More than 2 dupes.
504 {
505 MockRead data_reads[] = {
506 MockRead("HTTP/1.1 200 OK\r\n"),
507 MockRead("Content-Length: 5\r\n"),
508 MockRead("Content-Length: 5\r\n"),
509 MockRead("Content-Length: 5\r\n\r\n"),
510 MockRead("Hello"),
511 };
512 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
513 arraysize(data_reads));
514 EXPECT_EQ(OK, out.rv);
515 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
516 EXPECT_EQ("Hello", out.response_data);
517 }
518 // HTTP/1.0
519 {
520 MockRead data_reads[] = {
521 MockRead("HTTP/1.0 200 OK\r\n"),
522 MockRead("Content-Length: 5\r\n"),
523 MockRead("Content-Length: 5\r\n"),
524 MockRead("Content-Length: 5\r\n\r\n"),
525 MockRead("Hello"),
526 };
527 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
528 arraysize(data_reads));
529 EXPECT_EQ(OK, out.rv);
530 EXPECT_EQ("HTTP/1.0 200 OK", out.status_line);
531 EXPECT_EQ("Hello", out.response_data);
532 }
533 // 2 dupes and one mismatched.
534 {
535 MockRead data_reads[] = {
536 MockRead("HTTP/1.1 200 OK\r\n"),
537 MockRead("Content-Length: 10\r\n"),
538 MockRead("Content-Length: 10\r\n"),
539 MockRead("Content-Length: 5\r\n\r\n"),
540 };
541 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
542 arraysize(data_reads));
543 EXPECT_EQ(ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH, out.rv);
544 }
545}
546
547TEST_F(HttpNetworkTransactionTest,
[email protected]9fe44f52010-09-23 18:36:00548 MultipleContentLengthHeadersTransferEncoding) {
549 MockRead data_reads[] = {
550 MockRead("HTTP/1.1 200 OK\r\n"),
551 MockRead("Content-Length: 666\r\n"),
552 MockRead("Content-Length: 1337\r\n"),
553 MockRead("Transfer-Encoding: chunked\r\n\r\n"),
554 MockRead("5\r\nHello\r\n"),
555 MockRead("1\r\n"),
556 MockRead(" \r\n"),
557 MockRead("5\r\nworld\r\n"),
558 MockRead("0\r\n\r\nHTTP/1.1 200 OK\r\n"),
559 MockRead(false, OK),
560 };
561 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
562 arraysize(data_reads));
563 EXPECT_EQ(OK, out.rv);
564 EXPECT_EQ("HTTP/1.1 200 OK", out.status_line);
565 EXPECT_EQ("Hello world", out.response_data);
566}
567
[email protected]ef0faf2e72009-03-05 23:27:23568// Do a request using the HEAD method. Verify that we don't try to read the
569// message body (since HEAD has none).
570TEST_F(HttpNetworkTransactionTest, Head) {
[email protected]1c773ea12009-04-28 19:58:42571 HttpRequestInfo request;
[email protected]ef0faf2e72009-03-05 23:27:23572 request.method = "HEAD";
573 request.url = GURL("http://www.google.com/");
574 request.load_flags = 0;
575
[email protected]cb9bf6ca2011-01-28 13:15:27576 SessionDependencies session_deps;
577 scoped_ptr<HttpTransaction> trans(
578 new HttpNetworkTransaction(CreateSession(&session_deps)));
579
[email protected]ef0faf2e72009-03-05 23:27:23580 MockWrite data_writes1[] = {
581 MockWrite("HEAD / HTTP/1.1\r\n"
582 "Host: www.google.com\r\n"
583 "Connection: keep-alive\r\n"
584 "Content-Length: 0\r\n\r\n"),
585 };
586 MockRead data_reads1[] = {
587 MockRead("HTTP/1.1 404 Not Found\r\n"),
588 MockRead("Server: Blah\r\n"),
589 MockRead("Content-Length: 1234\r\n\r\n"),
590
591 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:42592 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]ef0faf2e72009-03-05 23:27:23593 };
594
[email protected]31a2bfe2010-02-09 08:03:39595 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
596 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:59597 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]ef0faf2e72009-03-05 23:27:23598
599 TestCompletionCallback callback1;
600
[email protected]5a1d7ca2010-04-28 20:12:27601 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42602 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]ef0faf2e72009-03-05 23:27:23603
604 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42605 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23606
[email protected]1c773ea12009-04-28 19:58:42607 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]ef0faf2e72009-03-05 23:27:23608 EXPECT_FALSE(response == NULL);
609
610 // Check that the headers got parsed.
611 EXPECT_TRUE(response->headers != NULL);
612 EXPECT_EQ(1234, response->headers->GetContentLength());
613 EXPECT_EQ("HTTP/1.1 404 Not Found", response->headers->GetStatusLine());
614
615 std::string server_header;
616 void* iter = NULL;
617 bool has_server_header = response->headers->EnumerateHeader(
618 &iter, "Server", &server_header);
619 EXPECT_TRUE(has_server_header);
620 EXPECT_EQ("Blah", server_header);
621
622 // Reading should give EOF right away, since there is no message body
623 // (despite non-zero content-length).
624 std::string response_data;
625 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42626 EXPECT_EQ(OK, rv);
[email protected]ef0faf2e72009-03-05 23:27:23627 EXPECT_EQ("", response_data);
628}
629
initial.commit586acc5fe2008-07-26 22:42:52630TEST_F(HttpNetworkTransactionTest, ReuseConnection) {
[email protected]228ff742009-06-05 01:19:59631 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:27632 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
initial.commit586acc5fe2008-07-26 22:42:52633
634 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35635 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
636 MockRead("hello"),
637 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
638 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42639 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52640 };
[email protected]31a2bfe2010-02-09 08:03:39641 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59642 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52643
[email protected]0b0bf032010-09-21 18:08:50644 const char* const kExpectedResponseData[] = {
initial.commit586acc5fe2008-07-26 22:42:52645 "hello", "world"
646 };
647
648 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:42649 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52650 request.method = "GET";
651 request.url = GURL("http://www.google.com/");
652 request.load_flags = 0;
653
[email protected]cb9bf6ca2011-01-28 13:15:27654 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
655
initial.commit586acc5fe2008-07-26 22:42:52656 TestCompletionCallback callback;
657
[email protected]5a1d7ca2010-04-28 20:12:27658 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42659 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52660
661 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42662 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52663
[email protected]1c773ea12009-04-28 19:58:42664 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52665 EXPECT_TRUE(response != NULL);
666
667 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25668 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52669
670 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57671 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42672 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25673 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52674 }
675}
676
677TEST_F(HttpNetworkTransactionTest, Ignores100) {
[email protected]1c773ea12009-04-28 19:58:42678 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52679 request.method = "POST";
680 request.url = GURL("http://www.foo.com/");
[email protected]1c773ea12009-04-28 19:58:42681 request.upload_data = new UploadData;
initial.commit586acc5fe2008-07-26 22:42:52682 request.upload_data->AppendBytes("foo", 3);
683 request.load_flags = 0;
684
[email protected]cb9bf6ca2011-01-28 13:15:27685 SessionDependencies session_deps;
686 scoped_ptr<HttpTransaction> trans(
687 new HttpNetworkTransaction(CreateSession(&session_deps)));
688
initial.commit586acc5fe2008-07-26 22:42:52689 MockRead data_reads[] = {
[email protected]217e6022008-09-29 18:18:35690 MockRead("HTTP/1.0 100 Continue\r\n\r\n"),
691 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
692 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42693 MockRead(false, OK),
initial.commit586acc5fe2008-07-26 22:42:52694 };
[email protected]31a2bfe2010-02-09 08:03:39695 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59696 session_deps.socket_factory.AddSocketDataProvider(&data);
initial.commit586acc5fe2008-07-26 22:42:52697
698 TestCompletionCallback callback;
699
[email protected]5a1d7ca2010-04-28 20:12:27700 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42701 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52702
703 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42704 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52705
[email protected]1c773ea12009-04-28 19:58:42706 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52707 EXPECT_TRUE(response != NULL);
708
709 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25710 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52711
712 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57713 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42714 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25715 EXPECT_EQ("hello world", response_data);
initial.commit586acc5fe2008-07-26 22:42:52716}
717
[email protected]3a2d3662009-03-27 03:49:14718// This test is almost the same as Ignores100 above, but the response contains
719// a 102 instead of a 100. Also, instead of HTTP/1.0 the response is
[email protected]0877e3d2009-10-17 22:29:57720// HTTP/1.1 and the two status headers are read in one read.
[email protected]3a2d3662009-03-27 03:49:14721TEST_F(HttpNetworkTransactionTest, Ignores1xx) {
[email protected]1c773ea12009-04-28 19:58:42722 HttpRequestInfo request;
[email protected]3a2d3662009-03-27 03:49:14723 request.method = "GET";
724 request.url = GURL("http://www.foo.com/");
725 request.load_flags = 0;
726
[email protected]cb9bf6ca2011-01-28 13:15:27727 SessionDependencies session_deps;
728 scoped_ptr<HttpTransaction> trans(
729 new HttpNetworkTransaction(CreateSession(&session_deps)));
730
[email protected]3a2d3662009-03-27 03:49:14731 MockRead data_reads[] = {
[email protected]0877e3d2009-10-17 22:29:57732 MockRead("HTTP/1.1 102 Unspecified status code\r\n\r\n"
733 "HTTP/1.1 200 OK\r\n\r\n"),
[email protected]3a2d3662009-03-27 03:49:14734 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42735 MockRead(false, OK),
[email protected]3a2d3662009-03-27 03:49:14736 };
[email protected]31a2bfe2010-02-09 08:03:39737 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59738 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3a2d3662009-03-27 03:49:14739
740 TestCompletionCallback callback;
741
[email protected]5a1d7ca2010-04-28 20:12:27742 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42743 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3a2d3662009-03-27 03:49:14744
745 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42746 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14747
[email protected]1c773ea12009-04-28 19:58:42748 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3a2d3662009-03-27 03:49:14749 EXPECT_TRUE(response != NULL);
750
751 EXPECT_TRUE(response->headers != NULL);
752 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
753
754 std::string response_data;
755 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42756 EXPECT_EQ(OK, rv);
[email protected]3a2d3662009-03-27 03:49:14757 EXPECT_EQ("hello world", response_data);
758}
759
[email protected]ee9410e72010-01-07 01:42:38760TEST_F(HttpNetworkTransactionTest, Incomplete100ThenEOF) {
[email protected]ee9410e72010-01-07 01:42:38761 HttpRequestInfo request;
762 request.method = "POST";
763 request.url = GURL("http://www.foo.com/");
764 request.load_flags = 0;
765
[email protected]cb9bf6ca2011-01-28 13:15:27766 SessionDependencies session_deps;
767 scoped_ptr<HttpTransaction> trans(
768 new HttpNetworkTransaction(CreateSession(&session_deps)));
769
[email protected]ee9410e72010-01-07 01:42:38770 MockRead data_reads[] = {
771 MockRead(false, "HTTP/1.0 100 Continue\r\n"),
772 MockRead(true, 0),
773 };
[email protected]31a2bfe2010-02-09 08:03:39774 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38775 session_deps.socket_factory.AddSocketDataProvider(&data);
776
777 TestCompletionCallback callback;
778
[email protected]5a1d7ca2010-04-28 20:12:27779 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38780 EXPECT_EQ(ERR_IO_PENDING, rv);
781
782 rv = callback.WaitForResult();
783 EXPECT_EQ(OK, rv);
784
785 std::string response_data;
786 rv = ReadTransaction(trans.get(), &response_data);
787 EXPECT_EQ(OK, rv);
788 EXPECT_EQ("", response_data);
789}
790
791TEST_F(HttpNetworkTransactionTest, EmptyResponse) {
[email protected]ee9410e72010-01-07 01:42:38792 HttpRequestInfo request;
793 request.method = "POST";
794 request.url = GURL("http://www.foo.com/");
795 request.load_flags = 0;
796
[email protected]cb9bf6ca2011-01-28 13:15:27797 SessionDependencies session_deps;
798 scoped_ptr<HttpTransaction> trans(
799 new HttpNetworkTransaction(CreateSession(&session_deps)));
800
[email protected]ee9410e72010-01-07 01:42:38801 MockRead data_reads[] = {
802 MockRead(true, 0),
803 };
[email protected]31a2bfe2010-02-09 08:03:39804 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]ee9410e72010-01-07 01:42:38805 session_deps.socket_factory.AddSocketDataProvider(&data);
806
807 TestCompletionCallback callback;
808
[email protected]5a1d7ca2010-04-28 20:12:27809 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]ee9410e72010-01-07 01:42:38810 EXPECT_EQ(ERR_IO_PENDING, rv);
811
812 rv = callback.WaitForResult();
813 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
814}
815
[email protected]3d2a59b2008-09-26 19:44:25816// read_failure specifies a read failure that should cause the network
817// transaction to resend the request.
818void HttpNetworkTransactionTest::KeepAliveConnectionResendRequestTest(
819 const MockRead& read_failure) {
[email protected]1c773ea12009-04-28 19:58:42820 HttpRequestInfo request;
initial.commit586acc5fe2008-07-26 22:42:52821 request.method = "GET";
822 request.url = GURL("http://www.foo.com/");
823 request.load_flags = 0;
824
[email protected]cb9bf6ca2011-01-28 13:15:27825 SessionDependencies session_deps;
826 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
827
initial.commit586acc5fe2008-07-26 22:42:52828 MockRead data1_reads[] = {
[email protected]217e6022008-09-29 18:18:35829 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
830 MockRead("hello"),
[email protected]3d2a59b2008-09-26 19:44:25831 read_failure, // Now, we reuse the connection and fail the first read.
initial.commit586acc5fe2008-07-26 22:42:52832 };
[email protected]31a2bfe2010-02-09 08:03:39833 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59834 session_deps.socket_factory.AddSocketDataProvider(&data1);
initial.commit586acc5fe2008-07-26 22:42:52835
836 MockRead data2_reads[] = {
[email protected]217e6022008-09-29 18:18:35837 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
838 MockRead("world"),
[email protected]1c773ea12009-04-28 19:58:42839 MockRead(true, OK),
initial.commit586acc5fe2008-07-26 22:42:52840 };
[email protected]31a2bfe2010-02-09 08:03:39841 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59842 session_deps.socket_factory.AddSocketDataProvider(&data2);
initial.commit586acc5fe2008-07-26 22:42:52843
844 const char* kExpectedResponseData[] = {
845 "hello", "world"
846 };
847
848 for (int i = 0; i < 2; ++i) {
849 TestCompletionCallback callback;
850
[email protected]5695b8c2009-09-30 21:36:43851 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
initial.commit586acc5fe2008-07-26 22:42:52852
[email protected]5a1d7ca2010-04-28 20:12:27853 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42854 EXPECT_EQ(ERR_IO_PENDING, rv);
initial.commit586acc5fe2008-07-26 22:42:52855
856 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42857 EXPECT_EQ(OK, rv);
initial.commit586acc5fe2008-07-26 22:42:52858
[email protected]1c773ea12009-04-28 19:58:42859 const HttpResponseInfo* response = trans->GetResponseInfo();
initial.commit586acc5fe2008-07-26 22:42:52860 EXPECT_TRUE(response != NULL);
861
862 EXPECT_TRUE(response->headers != NULL);
[email protected]3d2a59b2008-09-26 19:44:25863 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
initial.commit586acc5fe2008-07-26 22:42:52864
865 std::string response_data;
[email protected]af4876d2008-10-21 23:10:57866 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:42867 EXPECT_EQ(OK, rv);
[email protected]3d2a59b2008-09-26 19:44:25868 EXPECT_EQ(kExpectedResponseData[i], response_data);
initial.commit586acc5fe2008-07-26 22:42:52869 }
870}
[email protected]3d2a59b2008-09-26 19:44:25871
872TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42873 MockRead read_failure(true, ERR_CONNECTION_RESET);
[email protected]3d2a59b2008-09-26 19:44:25874 KeepAliveConnectionResendRequestTest(read_failure);
875}
876
877TEST_F(HttpNetworkTransactionTest, KeepAliveConnectionEOF) {
[email protected]1c773ea12009-04-28 19:58:42878 MockRead read_failure(false, OK); // EOF
[email protected]3d2a59b2008-09-26 19:44:25879 KeepAliveConnectionResendRequestTest(read_failure);
880}
881
882TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionReset) {
[email protected]1c773ea12009-04-28 19:58:42883 HttpRequestInfo request;
[email protected]3d2a59b2008-09-26 19:44:25884 request.method = "GET";
885 request.url = GURL("http://www.google.com/");
886 request.load_flags = 0;
887
[email protected]cb9bf6ca2011-01-28 13:15:27888 SessionDependencies session_deps;
889 scoped_ptr<HttpTransaction> trans(
890 new HttpNetworkTransaction(CreateSession(&session_deps)));
891
[email protected]3d2a59b2008-09-26 19:44:25892 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42893 MockRead(true, ERR_CONNECTION_RESET),
[email protected]217e6022008-09-29 18:18:35894 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
895 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42896 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25897 };
[email protected]31a2bfe2010-02-09 08:03:39898 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:59899 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3d2a59b2008-09-26 19:44:25900
901 TestCompletionCallback callback;
902
[email protected]5a1d7ca2010-04-28 20:12:27903 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:42904 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3d2a59b2008-09-26 19:44:25905
906 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:42907 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
[email protected]3d2a59b2008-09-26 19:44:25908
[email protected]1c773ea12009-04-28 19:58:42909 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]3d2a59b2008-09-26 19:44:25910 EXPECT_TRUE(response == NULL);
[email protected]3d2a59b2008-09-26 19:44:25911}
912
913// What do various browsers do when the server closes a non-keepalive
914// connection without sending any response header or body?
915//
916// IE7: error page
917// Safari 3.1.2 (Windows): error page
918// Firefox 3.0.1: blank page
919// Opera 9.52: after five attempts, blank page
[email protected]1c773ea12009-04-28 19:58:42920// Us with WinHTTP: error page (ERR_INVALID_RESPONSE)
921// Us: error page (EMPTY_RESPONSE)
[email protected]3d2a59b2008-09-26 19:44:25922TEST_F(HttpNetworkTransactionTest, NonKeepAliveConnectionEOF) {
923 MockRead data_reads[] = {
[email protected]1c773ea12009-04-28 19:58:42924 MockRead(false, OK), // EOF
[email protected]217e6022008-09-29 18:18:35925 MockRead("HTTP/1.0 200 OK\r\n\r\n"), // Should not be used
926 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:42927 MockRead(false, OK),
[email protected]3d2a59b2008-09-26 19:44:25928 };
[email protected]31a2bfe2010-02-09 08:03:39929 SimpleGetHelperResult out = SimpleGetHelper(data_reads,
930 arraysize(data_reads));
[email protected]1c773ea12009-04-28 19:58:42931 EXPECT_EQ(ERR_EMPTY_RESPONSE, out.rv);
[email protected]3d2a59b2008-09-26 19:44:25932}
[email protected]038e9a32008-10-08 22:40:16933
[email protected]0b0bf032010-09-21 18:08:50934// Test that we correctly reuse a keep-alive connection after not explicitly
935// reading the body.
936TEST_F(HttpNetworkTransactionTest, KeepAliveAfterUnreadBody) {
[email protected]fc31d6a42010-06-24 18:05:13937 HttpRequestInfo request;
938 request.method = "GET";
939 request.url = GURL("http://www.foo.com/");
940 request.load_flags = 0;
941
[email protected]cb9bf6ca2011-01-28 13:15:27942 SessionDependencies session_deps;
943 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
944
[email protected]0b0bf032010-09-21 18:08:50945 // Note that because all these reads happen in the same
946 // StaticSocketDataProvider, it shows that the same socket is being reused for
947 // all transactions.
[email protected]fc31d6a42010-06-24 18:05:13948 MockRead data1_reads[] = {
[email protected]0b0bf032010-09-21 18:08:50949 MockRead("HTTP/1.1 204 No Content\r\n\r\n"),
950 MockRead("HTTP/1.1 205 Reset Content\r\n\r\n"),
[email protected]fc31d6a42010-06-24 18:05:13951 MockRead("HTTP/1.1 304 Not Modified\r\n\r\n"),
[email protected]0b0bf032010-09-21 18:08:50952 MockRead("HTTP/1.1 302 Found\r\n"
953 "Content-Length: 0\r\n\r\n"),
954 MockRead("HTTP/1.1 302 Found\r\n"
955 "Content-Length: 5\r\n\r\n"
956 "hello"),
957 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
958 "Content-Length: 0\r\n\r\n"),
959 MockRead("HTTP/1.1 301 Moved Permanently\r\n"
960 "Content-Length: 5\r\n\r\n"
961 "hello"),
[email protected]fc31d6a42010-06-24 18:05:13962 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 5\r\n\r\n"),
963 MockRead("hello"),
964 };
965 StaticSocketDataProvider data1(data1_reads, arraysize(data1_reads), NULL, 0);
966 session_deps.socket_factory.AddSocketDataProvider(&data1);
967
968 MockRead data2_reads[] = {
969 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
970 };
971 StaticSocketDataProvider data2(data2_reads, arraysize(data2_reads), NULL, 0);
972 session_deps.socket_factory.AddSocketDataProvider(&data2);
973
[email protected]0b0bf032010-09-21 18:08:50974 const int kNumUnreadBodies = arraysize(data1_reads) - 2;
975 std::string response_lines[kNumUnreadBodies];
976
977 for (size_t i = 0; i < arraysize(data1_reads) - 2; ++i) {
[email protected]fc31d6a42010-06-24 18:05:13978 TestCompletionCallback callback;
979
980 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
981
982 int rv = trans->Start(&request, &callback, BoundNetLog());
983 EXPECT_EQ(ERR_IO_PENDING, rv);
984
985 rv = callback.WaitForResult();
986 EXPECT_EQ(OK, rv);
987
988 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]0b0bf032010-09-21 18:08:50989 ASSERT_TRUE(response != NULL);
[email protected]fc31d6a42010-06-24 18:05:13990
[email protected]0b0bf032010-09-21 18:08:50991 ASSERT_TRUE(response->headers != NULL);
992 response_lines[i] = response->headers->GetStatusLine();
993
994 // We intentionally don't read the response bodies.
[email protected]fc31d6a42010-06-24 18:05:13995 }
[email protected]0b0bf032010-09-21 18:08:50996
997 const char* const kStatusLines[] = {
998 "HTTP/1.1 204 No Content",
999 "HTTP/1.1 205 Reset Content",
1000 "HTTP/1.1 304 Not Modified",
1001 "HTTP/1.1 302 Found",
1002 "HTTP/1.1 302 Found",
1003 "HTTP/1.1 301 Moved Permanently",
1004 "HTTP/1.1 301 Moved Permanently",
1005 };
1006
1007 COMPILE_ASSERT(kNumUnreadBodies == arraysize(kStatusLines),
1008 forgot_to_update_kStatusLines);
1009
1010 for (int i = 0; i < kNumUnreadBodies; ++i)
1011 EXPECT_EQ(kStatusLines[i], response_lines[i]);
1012
1013 TestCompletionCallback callback;
1014 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1015 int rv = trans->Start(&request, &callback, BoundNetLog());
1016 EXPECT_EQ(ERR_IO_PENDING, rv);
1017 rv = callback.WaitForResult();
1018 EXPECT_EQ(OK, rv);
1019 const HttpResponseInfo* response = trans->GetResponseInfo();
1020 ASSERT_TRUE(response != NULL);
1021 ASSERT_TRUE(response->headers != NULL);
1022 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1023 std::string response_data;
1024 rv = ReadTransaction(trans.get(), &response_data);
1025 EXPECT_EQ(OK, rv);
1026 EXPECT_EQ("hello", response_data);
[email protected]fc31d6a42010-06-24 18:05:131027}
1028
[email protected]038e9a32008-10-08 22:40:161029// Test the request-challenge-retry sequence for basic auth.
1030// (basic auth is the easiest to mock, because it has no randomness).
1031TEST_F(HttpNetworkTransactionTest, BasicAuth) {
[email protected]1c773ea12009-04-28 19:58:421032 HttpRequestInfo request;
[email protected]038e9a32008-10-08 22:40:161033 request.method = "GET";
1034 request.url = GURL("http://www.google.com/");
1035 request.load_flags = 0;
1036
[email protected]cb9bf6ca2011-01-28 13:15:271037 SessionDependencies session_deps;
1038 scoped_ptr<HttpTransaction> trans(
1039 new HttpNetworkTransaction(CreateSession(&session_deps)));
1040
[email protected]f9ee6b52008-11-08 06:46:231041 MockWrite data_writes1[] = {
1042 MockWrite("GET / HTTP/1.1\r\n"
1043 "Host: www.google.com\r\n"
1044 "Connection: keep-alive\r\n\r\n"),
1045 };
1046
[email protected]038e9a32008-10-08 22:40:161047 MockRead data_reads1[] = {
1048 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1049 // Give a couple authenticate options (only the middle one is actually
1050 // supported).
[email protected]22927ad2009-09-21 19:56:191051 MockRead("WWW-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:161052 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1053 MockRead("WWW-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
1054 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1055 // Large content-length -- won't matter, as connection will be reset.
1056 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421057 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:161058 };
1059
1060 // After calling trans->RestartWithAuth(), this is the request we should
1061 // be issuing -- the final header line contains the credentials.
1062 MockWrite data_writes2[] = {
1063 MockWrite("GET / HTTP/1.1\r\n"
1064 "Host: www.google.com\r\n"
1065 "Connection: keep-alive\r\n"
1066 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1067 };
1068
1069 // Lastly, the server responds with the actual content.
1070 MockRead data_reads2[] = {
1071 MockRead("HTTP/1.0 200 OK\r\n"),
1072 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1073 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421074 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:161075 };
1076
[email protected]31a2bfe2010-02-09 08:03:391077 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1078 data_writes1, arraysize(data_writes1));
1079 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1080 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:591081 session_deps.socket_factory.AddSocketDataProvider(&data1);
1082 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]038e9a32008-10-08 22:40:161083
1084 TestCompletionCallback callback1;
1085
[email protected]5a1d7ca2010-04-28 20:12:271086 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421087 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161088
1089 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421090 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161091
[email protected]1c773ea12009-04-28 19:58:421092 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:161093 EXPECT_FALSE(response == NULL);
1094
1095 // The password prompt info should have been set in response->auth_challenge.
1096 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1097
[email protected]71e4573a2009-05-21 22:03:001098 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:161099 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1100 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1101
1102 TestCompletionCallback callback2;
1103
[email protected]13c8a092010-07-29 06:15:441104 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421105 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:161106
1107 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421108 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:161109
1110 response = trans->GetResponseInfo();
1111 EXPECT_FALSE(response == NULL);
1112 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1113 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:161114}
1115
[email protected]861fcd52009-08-26 02:33:461116TEST_F(HttpNetworkTransactionTest, DoNotSendAuth) {
[email protected]861fcd52009-08-26 02:33:461117 HttpRequestInfo request;
1118 request.method = "GET";
1119 request.url = GURL("http://www.google.com/");
1120 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1121
[email protected]cb9bf6ca2011-01-28 13:15:271122 SessionDependencies session_deps;
1123 scoped_ptr<HttpTransaction> trans(
1124 new HttpNetworkTransaction(CreateSession(&session_deps)));
1125
[email protected]861fcd52009-08-26 02:33:461126 MockWrite data_writes[] = {
1127 MockWrite("GET / HTTP/1.1\r\n"
1128 "Host: www.google.com\r\n"
1129 "Connection: keep-alive\r\n\r\n"),
1130 };
1131
1132 MockRead data_reads[] = {
1133 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
1134 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1135 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1136 // Large content-length -- won't matter, as connection will be reset.
1137 MockRead("Content-Length: 10000\r\n\r\n"),
1138 MockRead(false, ERR_FAILED),
1139 };
1140
[email protected]31a2bfe2010-02-09 08:03:391141 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1142 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591143 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]861fcd52009-08-26 02:33:461144 TestCompletionCallback callback;
1145
[email protected]5a1d7ca2010-04-28 20:12:271146 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]861fcd52009-08-26 02:33:461147 EXPECT_EQ(ERR_IO_PENDING, rv);
1148
1149 rv = callback.WaitForResult();
1150 EXPECT_EQ(0, rv);
1151
1152 const HttpResponseInfo* response = trans->GetResponseInfo();
1153 ASSERT_FALSE(response == NULL);
1154 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1155}
1156
[email protected]2d2697f92009-02-18 21:00:321157// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1158// connection.
1159TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAlive) {
[email protected]1c773ea12009-04-28 19:58:421160 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321161 request.method = "GET";
1162 request.url = GURL("http://www.google.com/");
1163 request.load_flags = 0;
1164
[email protected]cb9bf6ca2011-01-28 13:15:271165 SessionDependencies session_deps;
1166 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1167
[email protected]2d2697f92009-02-18 21:00:321168 MockWrite data_writes1[] = {
1169 MockWrite("GET / HTTP/1.1\r\n"
1170 "Host: www.google.com\r\n"
1171 "Connection: keep-alive\r\n\r\n"),
1172
1173 // After calling trans->RestartWithAuth(), this is the request we should
1174 // be issuing -- the final header line contains the credentials.
1175 MockWrite("GET / HTTP/1.1\r\n"
1176 "Host: www.google.com\r\n"
1177 "Connection: keep-alive\r\n"
1178 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1179 };
1180
1181 MockRead data_reads1[] = {
1182 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1183 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1184 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1185 MockRead("Content-Length: 14\r\n\r\n"),
1186 MockRead("Unauthorized\r\n"),
1187
1188 // Lastly, the server responds with the actual content.
1189 MockRead("HTTP/1.1 200 OK\r\n"),
1190 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501191 MockRead("Content-Length: 5\r\n\r\n"),
1192 MockRead("Hello"),
[email protected]2d2697f92009-02-18 21:00:321193 };
1194
[email protected]2d0a4f92011-05-05 16:38:461195 // If there is a regression where we disconnect a Keep-Alive
1196 // connection during an auth roundtrip, we'll end up reading this.
1197 MockRead data_reads2[] = {
1198 MockRead(false, ERR_FAILED),
1199 };
1200
[email protected]31a2bfe2010-02-09 08:03:391201 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1202 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461203 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1204 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591205 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461206 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321207
1208 TestCompletionCallback callback1;
1209
[email protected]0b0bf032010-09-21 18:08:501210 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271211 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421212 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321213
1214 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421215 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321216
[email protected]1c773ea12009-04-28 19:58:421217 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321218 EXPECT_FALSE(response == NULL);
1219
1220 // The password prompt info should have been set in response->auth_challenge.
1221 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1222
[email protected]71e4573a2009-05-21 22:03:001223 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321224 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1225 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1226
1227 TestCompletionCallback callback2;
1228
[email protected]13c8a092010-07-29 06:15:441229 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421230 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321231
1232 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421233 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321234
1235 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461236 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321237 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501238 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321239}
1240
1241// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1242// connection and with no response body to drain.
1243TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveNoBody) {
[email protected]1c773ea12009-04-28 19:58:421244 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321245 request.method = "GET";
1246 request.url = GURL("http://www.google.com/");
1247 request.load_flags = 0;
1248
[email protected]cb9bf6ca2011-01-28 13:15:271249 SessionDependencies session_deps;
1250 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1251
[email protected]2d2697f92009-02-18 21:00:321252 MockWrite data_writes1[] = {
1253 MockWrite("GET / HTTP/1.1\r\n"
1254 "Host: www.google.com\r\n"
1255 "Connection: keep-alive\r\n\r\n"),
1256
1257 // After calling trans->RestartWithAuth(), this is the request we should
1258 // be issuing -- the final header line contains the credentials.
1259 MockWrite("GET / HTTP/1.1\r\n"
1260 "Host: www.google.com\r\n"
1261 "Connection: keep-alive\r\n"
1262 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1263 };
1264
[email protected]2d2697f92009-02-18 21:00:321265 MockRead data_reads1[] = {
1266 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1267 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
[email protected]11203f012009-11-12 23:02:311268 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
[email protected]2d2697f92009-02-18 21:00:321269
1270 // Lastly, the server responds with the actual content.
1271 MockRead("HTTP/1.1 200 OK\r\n"),
1272 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501273 MockRead("Content-Length: 5\r\n\r\n"),
1274 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321275 };
1276
[email protected]2d0a4f92011-05-05 16:38:461277 // An incorrect reconnect would cause this to be read.
1278 MockRead data_reads2[] = {
1279 MockRead(false, ERR_FAILED),
1280 };
1281
[email protected]31a2bfe2010-02-09 08:03:391282 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1283 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461284 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1285 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591286 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461287 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321288
1289 TestCompletionCallback callback1;
1290
[email protected]0b0bf032010-09-21 18:08:501291 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271292 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421293 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321294
1295 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421296 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321297
[email protected]1c773ea12009-04-28 19:58:421298 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321299 EXPECT_FALSE(response == NULL);
1300
1301 // The password prompt info should have been set in response->auth_challenge.
1302 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1303
[email protected]71e4573a2009-05-21 22:03:001304 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321305 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1306 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1307
1308 TestCompletionCallback callback2;
1309
[email protected]13c8a092010-07-29 06:15:441310 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421311 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321312
1313 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421314 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321315
1316 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461317 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321318 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501319 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321320}
1321
1322// Test the request-challenge-retry sequence for basic auth, over a keep-alive
1323// connection and with a large response body to drain.
1324TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveLargeBody) {
[email protected]1c773ea12009-04-28 19:58:421325 HttpRequestInfo request;
[email protected]2d2697f92009-02-18 21:00:321326 request.method = "GET";
1327 request.url = GURL("http://www.google.com/");
1328 request.load_flags = 0;
1329
[email protected]cb9bf6ca2011-01-28 13:15:271330 SessionDependencies session_deps;
1331 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1332
[email protected]2d2697f92009-02-18 21:00:321333 MockWrite data_writes1[] = {
1334 MockWrite("GET / HTTP/1.1\r\n"
1335 "Host: www.google.com\r\n"
1336 "Connection: keep-alive\r\n\r\n"),
1337
1338 // After calling trans->RestartWithAuth(), this is the request we should
1339 // be issuing -- the final header line contains the credentials.
1340 MockWrite("GET / HTTP/1.1\r\n"
1341 "Host: www.google.com\r\n"
1342 "Connection: keep-alive\r\n"
1343 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1344 };
1345
1346 // Respond with 5 kb of response body.
1347 std::string large_body_string("Unauthorized");
1348 large_body_string.append(5 * 1024, ' ');
1349 large_body_string.append("\r\n");
1350
1351 MockRead data_reads1[] = {
1352 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1353 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1354 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1355 // 5134 = 12 + 5 * 1024 + 2
1356 MockRead("Content-Length: 5134\r\n\r\n"),
1357 MockRead(true, large_body_string.data(), large_body_string.size()),
1358
1359 // Lastly, the server responds with the actual content.
1360 MockRead("HTTP/1.1 200 OK\r\n"),
1361 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501362 MockRead("Content-Length: 5\r\n\r\n"),
1363 MockRead("hello"),
[email protected]2d2697f92009-02-18 21:00:321364 };
1365
[email protected]2d0a4f92011-05-05 16:38:461366 // An incorrect reconnect would cause this to be read.
1367 MockRead data_reads2[] = {
1368 MockRead(false, ERR_FAILED),
1369 };
1370
[email protected]31a2bfe2010-02-09 08:03:391371 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1372 data_writes1, arraysize(data_writes1));
[email protected]2d0a4f92011-05-05 16:38:461373 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1374 NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:591375 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d0a4f92011-05-05 16:38:461376 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]2d2697f92009-02-18 21:00:321377
1378 TestCompletionCallback callback1;
1379
[email protected]0b0bf032010-09-21 18:08:501380 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271381 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421382 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321383
1384 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421385 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321386
[email protected]1c773ea12009-04-28 19:58:421387 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321388 EXPECT_FALSE(response == NULL);
1389
1390 // The password prompt info should have been set in response->auth_challenge.
1391 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1392
[email protected]71e4573a2009-05-21 22:03:001393 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321394 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1395 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1396
1397 TestCompletionCallback callback2;
1398
[email protected]13c8a092010-07-29 06:15:441399 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:421400 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321401
1402 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421403 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321404
1405 response = trans->GetResponseInfo();
[email protected]2d0a4f92011-05-05 16:38:461406 ASSERT_FALSE(response == NULL);
[email protected]2d2697f92009-02-18 21:00:321407 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501408 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]2d2697f92009-02-18 21:00:321409}
1410
1411// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]11203f012009-11-12 23:02:311412// connection, but the server gets impatient and closes the connection.
1413TEST_F(HttpNetworkTransactionTest, BasicAuthKeepAliveImpatientServer) {
[email protected]11203f012009-11-12 23:02:311414 HttpRequestInfo request;
1415 request.method = "GET";
1416 request.url = GURL("http://www.google.com/");
1417 request.load_flags = 0;
1418
[email protected]cb9bf6ca2011-01-28 13:15:271419 SessionDependencies session_deps;
1420 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1421
[email protected]11203f012009-11-12 23:02:311422 MockWrite data_writes1[] = {
1423 MockWrite("GET / HTTP/1.1\r\n"
1424 "Host: www.google.com\r\n"
1425 "Connection: keep-alive\r\n\r\n"),
1426 // This simulates the seemingly successful write to a closed connection
1427 // if the bug is not fixed.
1428 MockWrite("GET / HTTP/1.1\r\n"
1429 "Host: www.google.com\r\n"
1430 "Connection: keep-alive\r\n"
1431 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1432 };
1433
1434 MockRead data_reads1[] = {
1435 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
1436 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1437 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1438 MockRead("Content-Length: 14\r\n\r\n"),
1439 // Tell MockTCPClientSocket to simulate the server closing the connection.
1440 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
1441 MockRead("Unauthorized\r\n"),
1442 MockRead(false, OK), // The server closes the connection.
1443 };
1444
1445 // After calling trans->RestartWithAuth(), this is the request we should
1446 // be issuing -- the final header line contains the credentials.
1447 MockWrite data_writes2[] = {
1448 MockWrite("GET / HTTP/1.1\r\n"
1449 "Host: www.google.com\r\n"
1450 "Connection: keep-alive\r\n"
1451 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1452 };
1453
1454 // Lastly, the server responds with the actual content.
1455 MockRead data_reads2[] = {
1456 MockRead("HTTP/1.1 200 OK\r\n"),
1457 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501458 MockRead("Content-Length: 5\r\n\r\n"),
1459 MockRead("hello"),
[email protected]11203f012009-11-12 23:02:311460 };
1461
[email protected]31a2bfe2010-02-09 08:03:391462 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1463 data_writes1, arraysize(data_writes1));
1464 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
1465 data_writes2, arraysize(data_writes2));
[email protected]11203f012009-11-12 23:02:311466 session_deps.socket_factory.AddSocketDataProvider(&data1);
1467 session_deps.socket_factory.AddSocketDataProvider(&data2);
1468
1469 TestCompletionCallback callback1;
1470
[email protected]0b0bf032010-09-21 18:08:501471 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]5a1d7ca2010-04-28 20:12:271472 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]11203f012009-11-12 23:02:311473 EXPECT_EQ(ERR_IO_PENDING, rv);
1474
1475 rv = callback1.WaitForResult();
1476 EXPECT_EQ(OK, rv);
1477
1478 const HttpResponseInfo* response = trans->GetResponseInfo();
1479 EXPECT_FALSE(response == NULL);
1480
1481 // The password prompt info should have been set in response->auth_challenge.
1482 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1483
1484 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
1485 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1486 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1487
1488 TestCompletionCallback callback2;
1489
[email protected]13c8a092010-07-29 06:15:441490 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]11203f012009-11-12 23:02:311491 EXPECT_EQ(ERR_IO_PENDING, rv);
1492
1493 rv = callback2.WaitForResult();
1494 EXPECT_EQ(OK, rv);
1495
1496 response = trans->GetResponseInfo();
1497 ASSERT_FALSE(response == NULL);
1498 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501499 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]11203f012009-11-12 23:02:311500}
1501
[email protected]394816e92010-08-03 07:38:591502// Test the request-challenge-retry sequence for basic auth, over a connection
1503// that requires a restart when setting up an SSL tunnel.
1504TEST_F(HttpNetworkTransactionTest, BasicAuthProxyNoKeepAlive) {
[email protected]394816e92010-08-03 07:38:591505 HttpRequestInfo request;
1506 request.method = "GET";
1507 request.url = GURL("https://www.google.com/");
1508 // when the no authentication data flag is set.
1509 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1510
[email protected]cb9bf6ca2011-01-28 13:15:271511 // Configure against proxy server "myproxy:70".
1512 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1513 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1514 session_deps.net_log = log.bound().net_log();
1515 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1516
[email protected]394816e92010-08-03 07:38:591517 // Since we have proxy, should try to establish tunnel.
1518 MockWrite data_writes1[] = {
1519 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1520 "Host: www.google.com\r\n"
1521 "Proxy-Connection: keep-alive\r\n\r\n"),
1522
1523 // After calling trans->RestartWithAuth(), this is the request we should
1524 // be issuing -- the final header line contains the credentials.
1525 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1526 "Host: www.google.com\r\n"
1527 "Proxy-Connection: keep-alive\r\n"
1528 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
1529
1530 MockWrite("GET / HTTP/1.1\r\n"
1531 "Host: www.google.com\r\n"
1532 "Connection: keep-alive\r\n\r\n"),
1533 };
1534
1535 // The proxy responds to the connect with a 407, using a persistent
1536 // connection.
1537 MockRead data_reads1[] = {
1538 // No credentials.
1539 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1540 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1541 MockRead("Proxy-Connection: close\r\n\r\n"),
1542
1543 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1544
1545 MockRead("HTTP/1.1 200 OK\r\n"),
1546 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
[email protected]0b0bf032010-09-21 18:08:501547 MockRead("Content-Length: 5\r\n\r\n"),
1548 MockRead(false, "hello"),
[email protected]394816e92010-08-03 07:38:591549 };
1550
1551 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1552 data_writes1, arraysize(data_writes1));
1553 session_deps.socket_factory.AddSocketDataProvider(&data1);
1554 SSLSocketDataProvider ssl(true, OK);
1555 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1556
1557 TestCompletionCallback callback1;
1558
[email protected]0b0bf032010-09-21 18:08:501559 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1560
[email protected]394816e92010-08-03 07:38:591561 int rv = trans->Start(&request, &callback1, log.bound());
1562 EXPECT_EQ(ERR_IO_PENDING, rv);
1563
1564 rv = callback1.WaitForResult();
1565 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401566 net::CapturingNetLog::EntryList entries;
1567 log.GetEntries(&entries);
[email protected]394816e92010-08-03 07:38:591568 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401569 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]394816e92010-08-03 07:38:591570 NetLog::PHASE_NONE);
1571 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401572 entries, pos,
[email protected]394816e92010-08-03 07:38:591573 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1574 NetLog::PHASE_NONE);
1575
1576 const HttpResponseInfo* response = trans->GetResponseInfo();
1577 ASSERT_FALSE(response == NULL);
1578
1579 EXPECT_EQ(407, response->headers->response_code());
1580 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1581
1582 // The password prompt info should have been set in response->auth_challenge.
1583 ASSERT_FALSE(response->auth_challenge.get() == NULL);
1584
1585 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
1586 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1587 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1588
1589 TestCompletionCallback callback2;
1590
1591 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
1592 EXPECT_EQ(ERR_IO_PENDING, rv);
1593
1594 rv = callback2.WaitForResult();
1595 EXPECT_EQ(OK, rv);
1596
1597 response = trans->GetResponseInfo();
1598 ASSERT_FALSE(response == NULL);
1599
1600 EXPECT_TRUE(response->headers->IsKeepAlive());
1601 EXPECT_EQ(200, response->headers->response_code());
[email protected]0b0bf032010-09-21 18:08:501602 EXPECT_EQ(5, response->headers->GetContentLength());
[email protected]394816e92010-08-03 07:38:591603 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1604
1605 // The password prompt info should not be set.
1606 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]0b0bf032010-09-21 18:08:501607
1608 trans.reset();
[email protected]102e27c2011-02-23 01:01:311609 session->CloseAllConnections();
[email protected]394816e92010-08-03 07:38:591610}
1611
[email protected]11203f012009-11-12 23:02:311612// Test the request-challenge-retry sequence for basic auth, over a keep-alive
[email protected]2d2697f92009-02-18 21:00:321613// proxy connection, when setting up an SSL tunnel.
1614TEST_F(HttpNetworkTransactionTest, BasicAuthProxyKeepAlive) {
[email protected]cb9bf6ca2011-01-28 13:15:271615 HttpRequestInfo request;
1616 request.method = "GET";
1617 request.url = GURL("https://www.google.com/");
1618 // Ensure that proxy authentication is attempted even
1619 // when the no authentication data flag is set.
1620 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
1621
[email protected]2d2697f92009-02-18 21:00:321622 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001623 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a7ea8832010-07-12 17:54:541624 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1625 session_deps.net_log = log.bound().net_log();
[email protected]228ff742009-06-05 01:19:591626 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]2d2697f92009-02-18 21:00:321627
[email protected]5695b8c2009-09-30 21:36:431628 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]2d2697f92009-02-18 21:00:321629
[email protected]2d2697f92009-02-18 21:00:321630 // Since we have proxy, should try to establish tunnel.
1631 MockWrite data_writes1[] = {
1632 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451633 "Host: www.google.com\r\n"
1634 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]2d2697f92009-02-18 21:00:321635
1636 // After calling trans->RestartWithAuth(), this is the request we should
1637 // be issuing -- the final header line contains the credentials.
1638 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1639 "Host: www.google.com\r\n"
[email protected]e44de5d2009-06-05 20:12:451640 "Proxy-Connection: keep-alive\r\n"
[email protected]2d2697f92009-02-18 21:00:321641 "Proxy-Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
1642 };
1643
1644 // The proxy responds to the connect with a 407, using a persistent
1645 // connection.
1646 MockRead data_reads1[] = {
1647 // No credentials.
1648 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1649 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1650 MockRead("Content-Length: 10\r\n\r\n"),
1651 MockRead("0123456789"),
1652
1653 // Wrong credentials (wrong password).
1654 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1655 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1656 MockRead("Content-Length: 10\r\n\r\n"),
1657 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:421658 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]2d2697f92009-02-18 21:00:321659 };
1660
[email protected]31a2bfe2010-02-09 08:03:391661 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1662 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:591663 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]2d2697f92009-02-18 21:00:321664
1665 TestCompletionCallback callback1;
1666
[email protected]dbb83db2010-05-11 18:13:391667 int rv = trans->Start(&request, &callback1, log.bound());
[email protected]1c773ea12009-04-28 19:58:421668 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321669
1670 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421671 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:401672 net::CapturingNetLog::EntryList entries;
1673 log.GetEntries(&entries);
[email protected]dbb83db2010-05-11 18:13:391674 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401675 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]dbb83db2010-05-11 18:13:391676 NetLog::PHASE_NONE);
1677 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401678 entries, pos,
[email protected]dbb83db2010-05-11 18:13:391679 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1680 NetLog::PHASE_NONE);
[email protected]2d2697f92009-02-18 21:00:321681
[email protected]1c773ea12009-04-28 19:58:421682 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]2d2697f92009-02-18 21:00:321683 EXPECT_FALSE(response == NULL);
1684
1685 EXPECT_TRUE(response->headers->IsKeepAlive());
1686 EXPECT_EQ(407, response->headers->response_code());
1687 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421688 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321689
1690 // The password prompt info should have been set in response->auth_challenge.
1691 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1692
[email protected]71e4573a2009-05-21 22:03:001693 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321694 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1695 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
1696
1697 TestCompletionCallback callback2;
1698
1699 // Wrong password (should be "bar").
[email protected]13c8a092010-07-29 06:15:441700 rv = trans->RestartWithAuth(kFoo, kBaz, &callback2);
[email protected]1c773ea12009-04-28 19:58:421701 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]2d2697f92009-02-18 21:00:321702
1703 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421704 EXPECT_EQ(OK, rv);
[email protected]2d2697f92009-02-18 21:00:321705
1706 response = trans->GetResponseInfo();
1707 EXPECT_FALSE(response == NULL);
1708
1709 EXPECT_TRUE(response->headers->IsKeepAlive());
1710 EXPECT_EQ(407, response->headers->response_code());
1711 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421712 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]2d2697f92009-02-18 21:00:321713
1714 // The password prompt info should have been set in response->auth_challenge.
1715 EXPECT_FALSE(response->auth_challenge.get() == NULL);
1716
[email protected]71e4573a2009-05-21 22:03:001717 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]2d2697f92009-02-18 21:00:321718 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
1719 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
[email protected]e772db3f2010-07-12 18:11:131720
[email protected]e60e47a2010-07-14 03:37:181721 // Flush the idle socket before the NetLog and HttpNetworkTransaction go
1722 // out of scope.
[email protected]102e27c2011-02-23 01:01:311723 session->CloseAllConnections();
[email protected]2d2697f92009-02-18 21:00:321724}
1725
[email protected]a8e9b162009-03-12 00:06:441726// Test that we don't read the response body when we fail to establish a tunnel,
1727// even if the user cancels the proxy's auth attempt.
1728TEST_F(HttpNetworkTransactionTest, BasicAuthProxyCancelTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:271729 HttpRequestInfo request;
1730 request.method = "GET";
1731 request.url = GURL("https://www.google.com/");
1732 request.load_flags = 0;
1733
[email protected]a8e9b162009-03-12 00:06:441734 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:001735 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]a8e9b162009-03-12 00:06:441736
[email protected]e44de5d2009-06-05 20:12:451737 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]a8e9b162009-03-12 00:06:441738
[email protected]5695b8c2009-09-30 21:36:431739 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]a8e9b162009-03-12 00:06:441740
[email protected]a8e9b162009-03-12 00:06:441741 // Since we have proxy, should try to establish tunnel.
1742 MockWrite data_writes[] = {
1743 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:451744 "Host: www.google.com\r\n"
1745 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]a8e9b162009-03-12 00:06:441746 };
1747
1748 // The proxy responds to the connect with a 407.
1749 MockRead data_reads[] = {
1750 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
1751 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1752 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:421753 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]a8e9b162009-03-12 00:06:441754 };
1755
[email protected]31a2bfe2010-02-09 08:03:391756 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
1757 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:591758 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]a8e9b162009-03-12 00:06:441759
1760 TestCompletionCallback callback;
1761
[email protected]5a1d7ca2010-04-28 20:12:271762 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:421763 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]a8e9b162009-03-12 00:06:441764
1765 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:421766 EXPECT_EQ(OK, rv);
[email protected]a8e9b162009-03-12 00:06:441767
[email protected]1c773ea12009-04-28 19:58:421768 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]a8e9b162009-03-12 00:06:441769 EXPECT_FALSE(response == NULL);
1770
1771 EXPECT_TRUE(response->headers->IsKeepAlive());
1772 EXPECT_EQ(407, response->headers->response_code());
1773 EXPECT_EQ(10, response->headers->GetContentLength());
[email protected]1c773ea12009-04-28 19:58:421774 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
[email protected]a8e9b162009-03-12 00:06:441775
1776 std::string response_data;
1777 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:421778 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]e60e47a2010-07-14 03:37:181779
1780 // Flush the idle socket before the HttpNetworkTransaction goes out of scope.
[email protected]102e27c2011-02-23 01:01:311781 session->CloseAllConnections();
[email protected]a8e9b162009-03-12 00:06:441782}
1783
[email protected]8fdbcd22010-05-05 02:54:521784// Test when a server (non-proxy) returns a 407 (proxy-authenticate).
1785// The request should fail with ERR_UNEXPECTED_PROXY_AUTH.
1786TEST_F(HttpNetworkTransactionTest, UnexpectedProxyAuth) {
[email protected]8fdbcd22010-05-05 02:54:521787 HttpRequestInfo request;
1788 request.method = "GET";
1789 request.url = GURL("http://www.google.com/");
1790 request.load_flags = 0;
1791
[email protected]cb9bf6ca2011-01-28 13:15:271792 // We are using a DIRECT connection (i.e. no proxy) for this session.
1793 SessionDependencies session_deps;
1794 scoped_ptr<HttpTransaction> trans(
1795 new HttpNetworkTransaction(CreateSession(&session_deps)));
1796
[email protected]8fdbcd22010-05-05 02:54:521797 MockWrite data_writes1[] = {
1798 MockWrite("GET / HTTP/1.1\r\n"
1799 "Host: www.google.com\r\n"
1800 "Connection: keep-alive\r\n\r\n"),
1801 };
1802
1803 MockRead data_reads1[] = {
1804 MockRead("HTTP/1.0 407 Proxy Auth required\r\n"),
1805 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1806 // Large content-length -- won't matter, as connection will be reset.
1807 MockRead("Content-Length: 10000\r\n\r\n"),
1808 MockRead(false, ERR_FAILED),
1809 };
1810
1811 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1812 data_writes1, arraysize(data_writes1));
1813 session_deps.socket_factory.AddSocketDataProvider(&data1);
1814
1815 TestCompletionCallback callback;
1816
1817 int rv = trans->Start(&request, &callback, BoundNetLog());
1818 EXPECT_EQ(ERR_IO_PENDING, rv);
1819
1820 rv = callback.WaitForResult();
1821 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
1822}
1823
[email protected]7a67a8152010-11-05 18:31:101824// Tests when an HTTPS server (non-proxy) returns a 407 (proxy-authentication)
1825// through a non-authenticating proxy. The request should fail with
1826// ERR_UNEXPECTED_PROXY_AUTH.
1827// Note that it is impossible to detect if an HTTP server returns a 407 through
1828// a non-authenticating proxy - there is nothing to indicate whether the
1829// response came from the proxy or the server, so it is treated as if the proxy
1830// issued the challenge.
1831TEST_F(HttpNetworkTransactionTest, HttpsServerRequestsProxyAuthThroughProxy) {
[email protected]cb9bf6ca2011-01-28 13:15:271832 HttpRequestInfo request;
1833 request.method = "GET";
1834 request.url = GURL("https://www.google.com/");
1835
[email protected]7a67a8152010-11-05 18:31:101836 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
1837 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1838 session_deps.net_log = log.bound().net_log();
1839 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1840
[email protected]7a67a8152010-11-05 18:31:101841 // Since we have proxy, should try to establish tunnel.
1842 MockWrite data_writes1[] = {
1843 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
1844 "Host: www.google.com\r\n"
1845 "Proxy-Connection: keep-alive\r\n\r\n"),
1846
1847 MockWrite("GET / HTTP/1.1\r\n"
1848 "Host: www.google.com\r\n"
1849 "Connection: keep-alive\r\n\r\n"),
1850 };
1851
1852 MockRead data_reads1[] = {
1853 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
1854
1855 MockRead("HTTP/1.1 407 Unauthorized\r\n"),
1856 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
1857 MockRead("\r\n"),
1858 MockRead(false, OK),
1859 };
1860
1861 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1862 data_writes1, arraysize(data_writes1));
1863 session_deps.socket_factory.AddSocketDataProvider(&data1);
1864 SSLSocketDataProvider ssl(true, OK);
1865 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1866
1867 TestCompletionCallback callback1;
1868
1869 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1870
1871 int rv = trans->Start(&request, &callback1, log.bound());
1872 EXPECT_EQ(ERR_IO_PENDING, rv);
1873
1874 rv = callback1.WaitForResult();
1875 EXPECT_EQ(ERR_UNEXPECTED_PROXY_AUTH, rv);
[email protected]b2fcd0e2010-12-01 15:19:401876 net::CapturingNetLog::EntryList entries;
1877 log.GetEntries(&entries);
[email protected]7a67a8152010-11-05 18:31:101878 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401879 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]7a67a8152010-11-05 18:31:101880 NetLog::PHASE_NONE);
1881 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:401882 entries, pos,
[email protected]7a67a8152010-11-05 18:31:101883 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
1884 NetLog::PHASE_NONE);
1885}
[email protected]2df19bb2010-08-25 20:13:461886
1887// Test a simple get through an HTTPS Proxy.
1888TEST_F(HttpNetworkTransactionTest, HttpsProxyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271889 HttpRequestInfo request;
1890 request.method = "GET";
1891 request.url = GURL("http://www.google.com/");
1892
[email protected]2df19bb2010-08-25 20:13:461893 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001894 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:461895 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1896 session_deps.net_log = log.bound().net_log();
1897 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1898
[email protected]2df19bb2010-08-25 20:13:461899 // Since we have proxy, should use full url
1900 MockWrite data_writes1[] = {
1901 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
1902 "Host: www.google.com\r\n"
1903 "Proxy-Connection: keep-alive\r\n\r\n"),
1904 };
1905
1906 MockRead data_reads1[] = {
1907 MockRead("HTTP/1.1 200 OK\r\n"),
1908 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
1909 MockRead("Content-Length: 100\r\n\r\n"),
1910 MockRead(false, OK),
1911 };
1912
1913 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
1914 data_writes1, arraysize(data_writes1));
1915 session_deps.socket_factory.AddSocketDataProvider(&data1);
1916 SSLSocketDataProvider ssl(true, OK);
1917 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1918
1919 TestCompletionCallback callback1;
1920
[email protected]0b0bf032010-09-21 18:08:501921 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1922
[email protected]2df19bb2010-08-25 20:13:461923 int rv = trans->Start(&request, &callback1, log.bound());
1924 EXPECT_EQ(ERR_IO_PENDING, rv);
1925
1926 rv = callback1.WaitForResult();
1927 EXPECT_EQ(OK, rv);
1928
1929 const HttpResponseInfo* response = trans->GetResponseInfo();
1930 ASSERT_FALSE(response == NULL);
1931
1932 EXPECT_TRUE(response->headers->IsKeepAlive());
1933 EXPECT_EQ(200, response->headers->response_code());
1934 EXPECT_EQ(100, response->headers->GetContentLength());
1935 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
1936
1937 // The password prompt info should not be set.
1938 EXPECT_TRUE(response->auth_challenge.get() == NULL);
1939}
1940
[email protected]7642b5ae2010-09-01 20:55:171941// Test a SPDY get through an HTTPS Proxy.
1942TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGet) {
[email protected]cb9bf6ca2011-01-28 13:15:271943 HttpRequestInfo request;
1944 request.method = "GET";
1945 request.url = GURL("http://www.google.com/");
1946 request.load_flags = 0;
1947
[email protected]7642b5ae2010-09-01 20:55:171948 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:001949 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]7642b5ae2010-09-01 20:55:171950 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
1951 session_deps.net_log = log.bound().net_log();
1952 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
1953
[email protected]7642b5ae2010-09-01 20:55:171954 // fetch http://www.google.com/ via SPDY
1955 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST,
1956 false));
1957 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
1958
1959 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
1960 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
1961 MockRead spdy_reads[] = {
1962 CreateMockRead(*resp),
1963 CreateMockRead(*data),
1964 MockRead(true, 0, 0),
1965 };
1966
1967 scoped_refptr<DelayedSocketData> spdy_data(
1968 new DelayedSocketData(
1969 1, // wait for one write to finish before reading.
1970 spdy_reads, arraysize(spdy_reads),
1971 spdy_writes, arraysize(spdy_writes)));
1972 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
1973
1974 SSLSocketDataProvider ssl(true, OK);
1975 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
1976 ssl.next_proto = "spdy/2";
1977 ssl.was_npn_negotiated = true;
1978 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
1979
1980 TestCompletionCallback callback1;
1981
[email protected]0b0bf032010-09-21 18:08:501982 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
1983
[email protected]7642b5ae2010-09-01 20:55:171984 int rv = trans->Start(&request, &callback1, log.bound());
1985 EXPECT_EQ(ERR_IO_PENDING, rv);
1986
1987 rv = callback1.WaitForResult();
1988 EXPECT_EQ(OK, rv);
1989
1990 const HttpResponseInfo* response = trans->GetResponseInfo();
1991 ASSERT_TRUE(response != NULL);
1992 ASSERT_TRUE(response->headers != NULL);
1993 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
1994
1995 std::string response_data;
1996 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
1997 EXPECT_EQ(net::kUploadData, response_data);
1998}
1999
[email protected]dc7bd1c52010-11-12 00:01:132000// Test a SPDY get through an HTTPS Proxy.
2001TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyGetWithProxyAuth) {
[email protected]cb9bf6ca2011-01-28 13:15:272002 HttpRequestInfo request;
2003 request.method = "GET";
2004 request.url = GURL("http://www.google.com/");
2005 request.load_flags = 0;
2006
[email protected]dc7bd1c52010-11-12 00:01:132007 // Configure against https proxy server "proxy:70".
2008 SessionDependencies session_deps(
2009 ProxyService::CreateFixed("https://proxy:70"));
2010 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2011 session_deps.net_log = log.bound().net_log();
2012 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2013
[email protected]dc7bd1c52010-11-12 00:01:132014 // The first request will be a bare GET, the second request will be a
2015 // GET with a Proxy-Authorization header.
2016 scoped_ptr<spdy::SpdyFrame> req_get(
2017 ConstructSpdyGet(NULL, 0, false, 1, LOWEST, false));
2018 const char* const kExtraAuthorizationHeaders[] = {
2019 "proxy-authorization",
2020 "Basic Zm9vOmJhcg==",
2021 };
2022 scoped_ptr<spdy::SpdyFrame> req_get_authorization(
2023 ConstructSpdyGet(
2024 kExtraAuthorizationHeaders, arraysize(kExtraAuthorizationHeaders)/2,
2025 false, 3, LOWEST, false));
2026 MockWrite spdy_writes[] = {
2027 CreateMockWrite(*req_get, 1),
2028 CreateMockWrite(*req_get_authorization, 4),
2029 };
2030
2031 // The first response is a 407 proxy authentication challenge, and the second
2032 // response will be a 200 response since the second request includes a valid
2033 // Authorization header.
2034 const char* const kExtraAuthenticationHeaders[] = {
2035 "Proxy-Authenticate",
2036 "Basic realm=\"MyRealm1\""
2037 };
2038 scoped_ptr<spdy::SpdyFrame> resp_authentication(
2039 ConstructSpdySynReplyError(
2040 "407 Proxy Authentication Required",
2041 kExtraAuthenticationHeaders, arraysize(kExtraAuthenticationHeaders)/2,
2042 1));
2043 scoped_ptr<spdy::SpdyFrame> body_authentication(
2044 ConstructSpdyBodyFrame(1, true));
2045 scoped_ptr<spdy::SpdyFrame> resp_data(ConstructSpdyGetSynReply(NULL, 0, 3));
2046 scoped_ptr<spdy::SpdyFrame> body_data(ConstructSpdyBodyFrame(3, true));
2047 MockRead spdy_reads[] = {
2048 CreateMockRead(*resp_authentication, 2),
2049 CreateMockRead(*body_authentication, 3),
2050 CreateMockRead(*resp_data, 5),
2051 CreateMockRead(*body_data, 6),
2052 MockRead(true, 0, 7),
2053 };
2054
2055 scoped_refptr<OrderedSocketData> data(
2056 new OrderedSocketData(spdy_reads, arraysize(spdy_reads),
2057 spdy_writes, arraysize(spdy_writes)));
2058 session_deps.socket_factory.AddSocketDataProvider(data);
2059
2060 SSLSocketDataProvider ssl(true, OK);
2061 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2062 ssl.next_proto = "spdy/2";
2063 ssl.was_npn_negotiated = true;
2064 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2065
2066 TestCompletionCallback callback1;
2067
2068 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2069
2070 int rv = trans->Start(&request, &callback1, log.bound());
2071 EXPECT_EQ(ERR_IO_PENDING, rv);
2072
2073 rv = callback1.WaitForResult();
2074 EXPECT_EQ(OK, rv);
2075
2076 const HttpResponseInfo* const response = trans->GetResponseInfo();
2077
2078 ASSERT_TRUE(response != NULL);
2079 ASSERT_TRUE(response->headers != NULL);
2080 EXPECT_EQ(407, response->headers->response_code());
2081 EXPECT_TRUE(response->was_fetched_via_spdy);
2082
2083 // The password prompt info should have been set in response->auth_challenge.
2084 ASSERT_TRUE(response->auth_challenge.get() != NULL);
2085 EXPECT_TRUE(response->auth_challenge->is_proxy);
2086 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2087 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2088 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2089
2090 TestCompletionCallback callback2;
2091
2092 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2093 EXPECT_EQ(ERR_IO_PENDING, rv);
2094
2095 rv = callback2.WaitForResult();
2096 EXPECT_EQ(OK, rv);
2097
2098 const HttpResponseInfo* const response_restart = trans->GetResponseInfo();
2099
2100 ASSERT_TRUE(response_restart != NULL);
2101 ASSERT_TRUE(response_restart->headers != NULL);
2102 EXPECT_EQ(200, response_restart->headers->response_code());
2103 // The password prompt info should not be set.
2104 EXPECT_TRUE(response_restart->auth_challenge.get() == NULL);
2105}
2106
[email protected]d9da5fe2010-10-13 22:37:162107// Test a SPDY CONNECT through an HTTPS Proxy to an HTTPS (non-SPDY) Server.
2108TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectHttps) {
[email protected]cb9bf6ca2011-01-28 13:15:272109 HttpRequestInfo request;
2110 request.method = "GET";
2111 request.url = GURL("https://www.google.com/");
2112 request.load_flags = 0;
2113
[email protected]d9da5fe2010-10-13 22:37:162114 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002115 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162116 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2117 session_deps.net_log = log.bound().net_log();
2118 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2119
2120 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2121
[email protected]d9da5fe2010-10-13 22:37:162122 // CONNECT to www.google.com:443 via SPDY
2123 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2124 // fetch https://www.google.com/ via HTTP
2125
2126 const char get[] = "GET / HTTP/1.1\r\n"
2127 "Host: www.google.com\r\n"
2128 "Connection: keep-alive\r\n\r\n";
2129 scoped_ptr<spdy::SpdyFrame> wrapped_get(
2130 ConstructSpdyBodyFrame(1, get, strlen(get), false));
2131 MockWrite spdy_writes[] = {
2132 CreateMockWrite(*connect, 1),
2133 CreateMockWrite(*wrapped_get, 3)
2134 };
2135
2136 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2137 const char resp[] = "HTTP/1.1 200 OK\r\n"
2138 "Content-Length: 10\r\n\r\n";
2139
2140 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2141 ConstructSpdyBodyFrame(1, resp, strlen(resp), false));
2142 scoped_ptr<spdy::SpdyFrame> wrapped_body(
2143 ConstructSpdyBodyFrame(1, "1234567890", 10, false));
2144 MockRead spdy_reads[] = {
2145 CreateMockRead(*conn_resp, 2, true),
2146 CreateMockRead(*wrapped_get_resp, 4, true),
2147 CreateMockRead(*wrapped_body, 5, true),
2148 CreateMockRead(*wrapped_body, 6, true),
2149 MockRead(true, 0, 7),
2150 };
2151
2152 scoped_refptr<OrderedSocketData> spdy_data(
2153 new OrderedSocketData(
2154 spdy_reads, arraysize(spdy_reads),
2155 spdy_writes, arraysize(spdy_writes)));
2156 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2157
2158 SSLSocketDataProvider ssl(true, OK);
2159 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2160 ssl.next_proto = "spdy/2";
2161 ssl.was_npn_negotiated = true;
2162 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2163 SSLSocketDataProvider ssl2(true, OK);
2164 ssl2.was_npn_negotiated = false;
2165 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2166
2167 TestCompletionCallback callback1;
2168
2169 int rv = trans->Start(&request, &callback1, log.bound());
2170 EXPECT_EQ(ERR_IO_PENDING, rv);
2171
2172 rv = callback1.WaitForResult();
2173 EXPECT_EQ(OK, rv);
2174
2175 const HttpResponseInfo* response = trans->GetResponseInfo();
2176 ASSERT_TRUE(response != NULL);
2177 ASSERT_TRUE(response->headers != NULL);
2178 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2179
2180 std::string response_data;
2181 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2182 EXPECT_EQ("1234567890", response_data);
2183}
2184
2185// Test a SPDY CONNECT through an HTTPS Proxy to a SPDY server.
2186TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectSpdy) {
[email protected]cb9bf6ca2011-01-28 13:15:272187 HttpRequestInfo request;
2188 request.method = "GET";
2189 request.url = GURL("https://www.google.com/");
2190 request.load_flags = 0;
2191
[email protected]d9da5fe2010-10-13 22:37:162192 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002193 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162194 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2195 session_deps.net_log = log.bound().net_log();
2196 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2197
2198 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2199
[email protected]d9da5fe2010-10-13 22:37:162200 // CONNECT to www.google.com:443 via SPDY
2201 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2202 // fetch https://www.google.com/ via SPDY
2203 const char* const kMyUrl = "https://www.google.com/";
2204 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyGet(kMyUrl, false, 1, LOWEST));
2205 scoped_ptr<spdy::SpdyFrame> wrapped_get(ConstructWrappedSpdyFrame(get, 1));
2206 MockWrite spdy_writes[] = {
2207 CreateMockWrite(*connect, 1),
2208 CreateMockWrite(*wrapped_get, 3)
2209 };
2210
2211 scoped_ptr<spdy::SpdyFrame> conn_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2212 scoped_ptr<spdy::SpdyFrame> get_resp(ConstructSpdyGetSynReply(NULL, 0, 1));
2213 scoped_ptr<spdy::SpdyFrame> wrapped_get_resp(
2214 ConstructWrappedSpdyFrame(get_resp, 1));
2215 scoped_ptr<spdy::SpdyFrame> body(ConstructSpdyBodyFrame(1, true));
2216 scoped_ptr<spdy::SpdyFrame> wrapped_body(ConstructWrappedSpdyFrame(body, 1));
2217 MockRead spdy_reads[] = {
2218 CreateMockRead(*conn_resp, 2, true),
2219 CreateMockRead(*wrapped_get_resp, 4, true),
2220 CreateMockRead(*wrapped_body, 5, true),
2221 MockRead(true, 0, 1),
2222 };
2223
2224 scoped_refptr<OrderedSocketData> spdy_data(
2225 new OrderedSocketData(
2226 spdy_reads, arraysize(spdy_reads),
2227 spdy_writes, arraysize(spdy_writes)));
2228 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2229
2230 SSLSocketDataProvider ssl(true, OK);
2231 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2232 ssl.next_proto = "spdy/2";
2233 ssl.was_npn_negotiated = true;
2234 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2235 SSLSocketDataProvider ssl2(true, OK);
2236 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2237 ssl2.next_proto = "spdy/2";
2238 ssl2.was_npn_negotiated = true;
2239 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2240
2241 TestCompletionCallback callback1;
2242
2243 int rv = trans->Start(&request, &callback1, log.bound());
2244 EXPECT_EQ(ERR_IO_PENDING, rv);
2245
2246 rv = callback1.WaitForResult();
2247 EXPECT_EQ(OK, rv);
2248
2249 const HttpResponseInfo* response = trans->GetResponseInfo();
2250 ASSERT_TRUE(response != NULL);
2251 ASSERT_TRUE(response->headers != NULL);
2252 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
2253
2254 std::string response_data;
2255 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
2256 EXPECT_EQ(net::kUploadData, response_data);
2257}
2258
2259// Test a SPDY CONNECT failure through an HTTPS Proxy.
2260TEST_F(HttpNetworkTransactionTest, HttpsProxySpdyConnectFailure) {
[email protected]cb9bf6ca2011-01-28 13:15:272261 HttpRequestInfo request;
2262 request.method = "GET";
2263 request.url = GURL("https://www.google.com/");
2264 request.load_flags = 0;
2265
[email protected]d9da5fe2010-10-13 22:37:162266 // Configure against https proxy server "proxy:70".
[email protected]81cdfcd2010-10-16 00:49:002267 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]d9da5fe2010-10-13 22:37:162268 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2269 session_deps.net_log = log.bound().net_log();
2270 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2271
2272 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2273
[email protected]d9da5fe2010-10-13 22:37:162274 // CONNECT to www.google.com:443 via SPDY
2275 scoped_ptr<spdy::SpdyFrame> connect(ConstructSpdyConnect(NULL, 0, 1));
2276 scoped_ptr<spdy::SpdyFrame> get(ConstructSpdyRstStream(1, spdy::CANCEL));
2277
2278 MockWrite spdy_writes[] = {
2279 CreateMockWrite(*connect, 1),
2280 CreateMockWrite(*get, 3),
2281 };
2282
2283 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdySynReplyError(1));
2284 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
2285 MockRead spdy_reads[] = {
2286 CreateMockRead(*resp, 2, true),
2287 MockRead(true, 0, 4),
2288 };
2289
2290 scoped_refptr<OrderedSocketData> spdy_data(
2291 new OrderedSocketData(
2292 spdy_reads, arraysize(spdy_reads),
2293 spdy_writes, arraysize(spdy_writes)));
2294 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
2295
2296 SSLSocketDataProvider ssl(true, OK);
2297 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2298 ssl.next_proto = "spdy/2";
2299 ssl.was_npn_negotiated = true;
2300 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2301 SSLSocketDataProvider ssl2(true, OK);
2302 ssl2.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
2303 ssl2.next_proto = "spdy/2";
2304 ssl2.was_npn_negotiated = true;
2305 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
2306
2307 TestCompletionCallback callback1;
2308
2309 int rv = trans->Start(&request, &callback1, log.bound());
2310 EXPECT_EQ(ERR_IO_PENDING, rv);
2311
2312 rv = callback1.WaitForResult();
[email protected]511f6f52010-12-17 03:58:292313 EXPECT_EQ(OK, rv);
[email protected]d9da5fe2010-10-13 22:37:162314
2315 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]511f6f52010-12-17 03:58:292316 ASSERT_FALSE(response == NULL);
2317 EXPECT_EQ(500, response->headers->response_code());
[email protected]d9da5fe2010-10-13 22:37:162318}
2319
[email protected]2df19bb2010-08-25 20:13:462320// Test the challenge-response-retry sequence through an HTTPS Proxy
2321TEST_F(HttpNetworkTransactionTest, HttpsProxyAuthRetry) {
[email protected]2df19bb2010-08-25 20:13:462322 HttpRequestInfo request;
2323 request.method = "GET";
2324 request.url = GURL("http://www.google.com/");
2325 // when the no authentication data flag is set.
2326 request.load_flags = net::LOAD_DO_NOT_SEND_AUTH_DATA;
2327
[email protected]cb9bf6ca2011-01-28 13:15:272328 // Configure against https proxy server "proxy:70".
2329 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
2330 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
2331 session_deps.net_log = log.bound().net_log();
2332 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2333
[email protected]2df19bb2010-08-25 20:13:462334 // Since we have proxy, should use full url
2335 MockWrite data_writes1[] = {
2336 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2337 "Host: www.google.com\r\n"
2338 "Proxy-Connection: keep-alive\r\n\r\n"),
2339
2340 // After calling trans->RestartWithAuth(), this is the request we should
2341 // be issuing -- the final header line contains the credentials.
2342 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2343 "Host: www.google.com\r\n"
2344 "Proxy-Connection: keep-alive\r\n"
2345 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2346 };
2347
2348 // The proxy responds to the GET with a 407, using a persistent
2349 // connection.
2350 MockRead data_reads1[] = {
2351 // No credentials.
2352 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
2353 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2354 MockRead("Proxy-Connection: keep-alive\r\n"),
2355 MockRead("Content-Length: 0\r\n\r\n"),
2356
2357 MockRead("HTTP/1.1 200 OK\r\n"),
2358 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2359 MockRead("Content-Length: 100\r\n\r\n"),
2360 MockRead(false, OK),
2361 };
2362
2363 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2364 data_writes1, arraysize(data_writes1));
2365 session_deps.socket_factory.AddSocketDataProvider(&data1);
2366 SSLSocketDataProvider ssl(true, OK);
2367 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
2368
2369 TestCompletionCallback callback1;
2370
[email protected]0b0bf032010-09-21 18:08:502371 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2372
[email protected]2df19bb2010-08-25 20:13:462373 int rv = trans->Start(&request, &callback1, log.bound());
2374 EXPECT_EQ(ERR_IO_PENDING, rv);
2375
2376 rv = callback1.WaitForResult();
2377 EXPECT_EQ(OK, rv);
2378
2379 const HttpResponseInfo* response = trans->GetResponseInfo();
2380 ASSERT_FALSE(response == NULL);
2381
2382 EXPECT_EQ(407, response->headers->response_code());
2383 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2384
2385 // The password prompt info should have been set in response->auth_challenge.
2386 ASSERT_FALSE(response->auth_challenge.get() == NULL);
2387
2388 EXPECT_EQ(L"proxy:70", response->auth_challenge->host_and_port);
2389 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2390 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2391
2392 TestCompletionCallback callback2;
2393
2394 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
2395 EXPECT_EQ(ERR_IO_PENDING, rv);
2396
2397 rv = callback2.WaitForResult();
2398 EXPECT_EQ(OK, rv);
2399
2400 response = trans->GetResponseInfo();
2401 ASSERT_FALSE(response == NULL);
2402
2403 EXPECT_TRUE(response->headers->IsKeepAlive());
2404 EXPECT_EQ(200, response->headers->response_code());
2405 EXPECT_EQ(100, response->headers->GetContentLength());
2406 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
2407
2408 // The password prompt info should not be set.
2409 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2410}
2411
[email protected]ff007e162009-05-23 09:13:152412void HttpNetworkTransactionTest::ConnectStatusHelperWithExpectedStatus(
[email protected]c744cf22009-02-27 07:28:082413 const MockRead& status, int expected_status) {
[email protected]1c773ea12009-04-28 19:58:422414 HttpRequestInfo request;
[email protected]c744cf22009-02-27 07:28:082415 request.method = "GET";
2416 request.url = GURL("https://www.google.com/");
2417 request.load_flags = 0;
2418
[email protected]cb9bf6ca2011-01-28 13:15:272419 // Configure against proxy server "myproxy:70".
2420 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
2421
2422 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2423
[email protected]c744cf22009-02-27 07:28:082424 // Since we have proxy, should try to establish tunnel.
2425 MockWrite data_writes[] = {
2426 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:452427 "Host: www.google.com\r\n"
2428 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]c744cf22009-02-27 07:28:082429 };
2430
2431 MockRead data_reads[] = {
2432 status,
2433 MockRead("Content-Length: 10\r\n\r\n"),
2434 // No response body because the test stops reading here.
[email protected]1c773ea12009-04-28 19:58:422435 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]c744cf22009-02-27 07:28:082436 };
2437
[email protected]31a2bfe2010-02-09 08:03:392438 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
2439 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:592440 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]c744cf22009-02-27 07:28:082441
2442 TestCompletionCallback callback;
2443
[email protected]0b0bf032010-09-21 18:08:502444 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2445
[email protected]5a1d7ca2010-04-28 20:12:272446 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422447 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]c744cf22009-02-27 07:28:082448
2449 rv = callback.WaitForResult();
2450 EXPECT_EQ(expected_status, rv);
2451}
2452
[email protected]ff007e162009-05-23 09:13:152453void HttpNetworkTransactionTest::ConnectStatusHelper(const MockRead& status) {
[email protected]c744cf22009-02-27 07:28:082454 ConnectStatusHelperWithExpectedStatus(
[email protected]1c773ea12009-04-28 19:58:422455 status, ERR_TUNNEL_CONNECTION_FAILED);
[email protected]c744cf22009-02-27 07:28:082456}
2457
2458TEST_F(HttpNetworkTransactionTest, ConnectStatus100) {
2459 ConnectStatusHelper(MockRead("HTTP/1.1 100 Continue\r\n"));
2460}
2461
2462TEST_F(HttpNetworkTransactionTest, ConnectStatus101) {
2463 ConnectStatusHelper(MockRead("HTTP/1.1 101 Switching Protocols\r\n"));
2464}
2465
2466TEST_F(HttpNetworkTransactionTest, ConnectStatus201) {
2467 ConnectStatusHelper(MockRead("HTTP/1.1 201 Created\r\n"));
2468}
2469
2470TEST_F(HttpNetworkTransactionTest, ConnectStatus202) {
2471 ConnectStatusHelper(MockRead("HTTP/1.1 202 Accepted\r\n"));
2472}
2473
2474TEST_F(HttpNetworkTransactionTest, ConnectStatus203) {
2475 ConnectStatusHelper(
2476 MockRead("HTTP/1.1 203 Non-Authoritative Information\r\n"));
2477}
2478
2479TEST_F(HttpNetworkTransactionTest, ConnectStatus204) {
2480 ConnectStatusHelper(MockRead("HTTP/1.1 204 No Content\r\n"));
2481}
2482
2483TEST_F(HttpNetworkTransactionTest, ConnectStatus205) {
2484 ConnectStatusHelper(MockRead("HTTP/1.1 205 Reset Content\r\n"));
2485}
2486
2487TEST_F(HttpNetworkTransactionTest, ConnectStatus206) {
2488 ConnectStatusHelper(MockRead("HTTP/1.1 206 Partial Content\r\n"));
2489}
2490
2491TEST_F(HttpNetworkTransactionTest, ConnectStatus300) {
2492 ConnectStatusHelper(MockRead("HTTP/1.1 300 Multiple Choices\r\n"));
2493}
2494
2495TEST_F(HttpNetworkTransactionTest, ConnectStatus301) {
2496 ConnectStatusHelper(MockRead("HTTP/1.1 301 Moved Permanently\r\n"));
2497}
2498
2499TEST_F(HttpNetworkTransactionTest, ConnectStatus302) {
2500 ConnectStatusHelper(MockRead("HTTP/1.1 302 Found\r\n"));
2501}
2502
2503TEST_F(HttpNetworkTransactionTest, ConnectStatus303) {
2504 ConnectStatusHelper(MockRead("HTTP/1.1 303 See Other\r\n"));
2505}
2506
2507TEST_F(HttpNetworkTransactionTest, ConnectStatus304) {
2508 ConnectStatusHelper(MockRead("HTTP/1.1 304 Not Modified\r\n"));
2509}
2510
2511TEST_F(HttpNetworkTransactionTest, ConnectStatus305) {
2512 ConnectStatusHelper(MockRead("HTTP/1.1 305 Use Proxy\r\n"));
2513}
2514
2515TEST_F(HttpNetworkTransactionTest, ConnectStatus306) {
2516 ConnectStatusHelper(MockRead("HTTP/1.1 306\r\n"));
2517}
2518
2519TEST_F(HttpNetworkTransactionTest, ConnectStatus307) {
2520 ConnectStatusHelper(MockRead("HTTP/1.1 307 Temporary Redirect\r\n"));
2521}
2522
2523TEST_F(HttpNetworkTransactionTest, ConnectStatus400) {
2524 ConnectStatusHelper(MockRead("HTTP/1.1 400 Bad Request\r\n"));
2525}
2526
2527TEST_F(HttpNetworkTransactionTest, ConnectStatus401) {
2528 ConnectStatusHelper(MockRead("HTTP/1.1 401 Unauthorized\r\n"));
2529}
2530
2531TEST_F(HttpNetworkTransactionTest, ConnectStatus402) {
2532 ConnectStatusHelper(MockRead("HTTP/1.1 402 Payment Required\r\n"));
2533}
2534
2535TEST_F(HttpNetworkTransactionTest, ConnectStatus403) {
2536 ConnectStatusHelper(MockRead("HTTP/1.1 403 Forbidden\r\n"));
2537}
2538
2539TEST_F(HttpNetworkTransactionTest, ConnectStatus404) {
2540 ConnectStatusHelper(MockRead("HTTP/1.1 404 Not Found\r\n"));
2541}
2542
2543TEST_F(HttpNetworkTransactionTest, ConnectStatus405) {
2544 ConnectStatusHelper(MockRead("HTTP/1.1 405 Method Not Allowed\r\n"));
2545}
2546
2547TEST_F(HttpNetworkTransactionTest, ConnectStatus406) {
2548 ConnectStatusHelper(MockRead("HTTP/1.1 406 Not Acceptable\r\n"));
2549}
2550
2551TEST_F(HttpNetworkTransactionTest, ConnectStatus407) {
2552 ConnectStatusHelperWithExpectedStatus(
2553 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
[email protected]a7ea8832010-07-12 17:54:542554 ERR_PROXY_AUTH_UNSUPPORTED);
[email protected]c744cf22009-02-27 07:28:082555}
2556
2557TEST_F(HttpNetworkTransactionTest, ConnectStatus408) {
2558 ConnectStatusHelper(MockRead("HTTP/1.1 408 Request Timeout\r\n"));
2559}
2560
2561TEST_F(HttpNetworkTransactionTest, ConnectStatus409) {
2562 ConnectStatusHelper(MockRead("HTTP/1.1 409 Conflict\r\n"));
2563}
2564
2565TEST_F(HttpNetworkTransactionTest, ConnectStatus410) {
2566 ConnectStatusHelper(MockRead("HTTP/1.1 410 Gone\r\n"));
2567}
2568
2569TEST_F(HttpNetworkTransactionTest, ConnectStatus411) {
2570 ConnectStatusHelper(MockRead("HTTP/1.1 411 Length Required\r\n"));
2571}
2572
2573TEST_F(HttpNetworkTransactionTest, ConnectStatus412) {
2574 ConnectStatusHelper(MockRead("HTTP/1.1 412 Precondition Failed\r\n"));
2575}
2576
2577TEST_F(HttpNetworkTransactionTest, ConnectStatus413) {
2578 ConnectStatusHelper(MockRead("HTTP/1.1 413 Request Entity Too Large\r\n"));
2579}
2580
2581TEST_F(HttpNetworkTransactionTest, ConnectStatus414) {
2582 ConnectStatusHelper(MockRead("HTTP/1.1 414 Request-URI Too Long\r\n"));
2583}
2584
2585TEST_F(HttpNetworkTransactionTest, ConnectStatus415) {
2586 ConnectStatusHelper(MockRead("HTTP/1.1 415 Unsupported Media Type\r\n"));
2587}
2588
2589TEST_F(HttpNetworkTransactionTest, ConnectStatus416) {
2590 ConnectStatusHelper(
2591 MockRead("HTTP/1.1 416 Requested Range Not Satisfiable\r\n"));
2592}
2593
2594TEST_F(HttpNetworkTransactionTest, ConnectStatus417) {
2595 ConnectStatusHelper(MockRead("HTTP/1.1 417 Expectation Failed\r\n"));
2596}
2597
2598TEST_F(HttpNetworkTransactionTest, ConnectStatus500) {
2599 ConnectStatusHelper(MockRead("HTTP/1.1 500 Internal Server Error\r\n"));
2600}
2601
2602TEST_F(HttpNetworkTransactionTest, ConnectStatus501) {
2603 ConnectStatusHelper(MockRead("HTTP/1.1 501 Not Implemented\r\n"));
2604}
2605
2606TEST_F(HttpNetworkTransactionTest, ConnectStatus502) {
2607 ConnectStatusHelper(MockRead("HTTP/1.1 502 Bad Gateway\r\n"));
2608}
2609
2610TEST_F(HttpNetworkTransactionTest, ConnectStatus503) {
2611 ConnectStatusHelper(MockRead("HTTP/1.1 503 Service Unavailable\r\n"));
2612}
2613
2614TEST_F(HttpNetworkTransactionTest, ConnectStatus504) {
2615 ConnectStatusHelper(MockRead("HTTP/1.1 504 Gateway Timeout\r\n"));
2616}
2617
2618TEST_F(HttpNetworkTransactionTest, ConnectStatus505) {
2619 ConnectStatusHelper(MockRead("HTTP/1.1 505 HTTP Version Not Supported\r\n"));
2620}
2621
[email protected]038e9a32008-10-08 22:40:162622// Test the flow when both the proxy server AND origin server require
2623// authentication. Again, this uses basic auth for both since that is
2624// the simplest to mock.
2625TEST_F(HttpNetworkTransactionTest, BasicAuthProxyThenServer) {
[email protected]cb9bf6ca2011-01-28 13:15:272626 HttpRequestInfo request;
2627 request.method = "GET";
2628 request.url = GURL("http://www.google.com/");
2629 request.load_flags = 0;
2630
[email protected]81cdfcd2010-10-16 00:49:002631 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:012632
[email protected]038e9a32008-10-08 22:40:162633 // Configure against proxy server "myproxy:70".
[email protected]1c773ea12009-04-28 19:58:422634 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:432635 CreateSession(&session_deps)));
[email protected]038e9a32008-10-08 22:40:162636
[email protected]f9ee6b52008-11-08 06:46:232637 MockWrite data_writes1[] = {
2638 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2639 "Host: www.google.com\r\n"
2640 "Proxy-Connection: keep-alive\r\n\r\n"),
2641 };
2642
[email protected]038e9a32008-10-08 22:40:162643 MockRead data_reads1[] = {
2644 MockRead("HTTP/1.0 407 Unauthorized\r\n"),
2645 // Give a couple authenticate options (only the middle one is actually
2646 // supported).
[email protected]22927ad2009-09-21 19:56:192647 MockRead("Proxy-Authenticate: Basic invalid\r\n"), // Malformed.
[email protected]038e9a32008-10-08 22:40:162648 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2649 MockRead("Proxy-Authenticate: UNSUPPORTED realm=\"FOO\"\r\n"),
2650 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2651 // Large content-length -- won't matter, as connection will be reset.
2652 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422653 MockRead(false, ERR_FAILED),
[email protected]038e9a32008-10-08 22:40:162654 };
2655
2656 // After calling trans->RestartWithAuth() the first time, this is the
2657 // request we should be issuing -- the final header line contains the
2658 // proxy's credentials.
2659 MockWrite data_writes2[] = {
2660 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2661 "Host: www.google.com\r\n"
2662 "Proxy-Connection: keep-alive\r\n"
2663 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
2664 };
2665
2666 // Now the proxy server lets the request pass through to origin server.
2667 // The origin server responds with a 401.
2668 MockRead data_reads2[] = {
2669 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
2670 // Note: We are using the same realm-name as the proxy server. This is
2671 // completely valid, as realms are unique across hosts.
2672 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
2673 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2674 MockRead("Content-Length: 2000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422675 MockRead(false, ERR_FAILED), // Won't be reached.
[email protected]038e9a32008-10-08 22:40:162676 };
2677
2678 // After calling trans->RestartWithAuth() the second time, we should send
2679 // the credentials for both the proxy and origin server.
2680 MockWrite data_writes3[] = {
2681 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
2682 "Host: www.google.com\r\n"
2683 "Proxy-Connection: keep-alive\r\n"
2684 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n"
2685 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
2686 };
2687
2688 // Lastly we get the desired content.
2689 MockRead data_reads3[] = {
2690 MockRead("HTTP/1.0 200 OK\r\n"),
2691 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
2692 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:422693 MockRead(false, OK),
[email protected]038e9a32008-10-08 22:40:162694 };
2695
[email protected]31a2bfe2010-02-09 08:03:392696 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2697 data_writes1, arraysize(data_writes1));
2698 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2699 data_writes2, arraysize(data_writes2));
2700 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
2701 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:592702 session_deps.socket_factory.AddSocketDataProvider(&data1);
2703 session_deps.socket_factory.AddSocketDataProvider(&data2);
2704 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]038e9a32008-10-08 22:40:162705
2706 TestCompletionCallback callback1;
2707
[email protected]5a1d7ca2010-04-28 20:12:272708 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422709 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162710
2711 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422712 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162713
[email protected]1c773ea12009-04-28 19:58:422714 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]038e9a32008-10-08 22:40:162715 EXPECT_FALSE(response == NULL);
2716
2717 // The password prompt info should have been set in response->auth_challenge.
2718 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2719
[email protected]71e4573a2009-05-21 22:03:002720 EXPECT_EQ(L"myproxy:70", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162721 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2722 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2723
2724 TestCompletionCallback callback2;
2725
[email protected]13c8a092010-07-29 06:15:442726 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:422727 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162728
2729 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422730 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162731
2732 response = trans->GetResponseInfo();
2733 EXPECT_FALSE(response == NULL);
2734 EXPECT_FALSE(response->auth_challenge.get() == NULL);
2735
[email protected]71e4573a2009-05-21 22:03:002736 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]038e9a32008-10-08 22:40:162737 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
2738 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
2739
2740 TestCompletionCallback callback3;
2741
[email protected]13c8a092010-07-29 06:15:442742 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback3);
[email protected]1c773ea12009-04-28 19:58:422743 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]038e9a32008-10-08 22:40:162744
2745 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422746 EXPECT_EQ(OK, rv);
[email protected]038e9a32008-10-08 22:40:162747
2748 response = trans->GetResponseInfo();
2749 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2750 EXPECT_EQ(100, response->headers->GetContentLength());
[email protected]038e9a32008-10-08 22:40:162751}
[email protected]4ddaf2502008-10-23 18:26:192752
[email protected]ea9dc9a2009-09-05 00:43:322753// For the NTLM implementation using SSPI, we skip the NTLM tests since we
2754// can't hook into its internals to cause it to generate predictable NTLM
2755// authorization headers.
2756#if defined(NTLM_PORTABLE)
[email protected]385a4672009-03-11 22:21:292757// The NTLM authentication unit tests were generated by capturing the HTTP
2758// requests and responses using Fiddler 2 and inspecting the generated random
2759// bytes in the debugger.
2760
2761// Enter the correct password and authenticate successfully.
2762TEST_F(HttpNetworkTransactionTest, NTLMAuth1) {
[email protected]1c773ea12009-04-28 19:58:422763 HttpRequestInfo request;
[email protected]3f918782009-02-28 01:29:242764 request.method = "GET";
2765 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2766 request.load_flags = 0;
2767
[email protected]cb9bf6ca2011-01-28 13:15:272768 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom1,
2769 MockGetHostName);
2770 SessionDependencies session_deps;
2771 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2772
[email protected]3f918782009-02-28 01:29:242773 MockWrite data_writes1[] = {
2774 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2775 "Host: 172.22.68.17\r\n"
2776 "Connection: keep-alive\r\n\r\n"),
2777 };
2778
2779 MockRead data_reads1[] = {
2780 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042781 // Negotiate and NTLM are often requested together. However, we only want
2782 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2783 // the header that requests Negotiate for this test.
[email protected]3f918782009-02-28 01:29:242784 MockRead("WWW-Authenticate: NTLM\r\n"),
2785 MockRead("Connection: close\r\n"),
2786 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362787 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242788 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422789 MockRead(false, ERR_UNEXPECTED),
[email protected]3f918782009-02-28 01:29:242790 };
2791
2792 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222793 // After restarting with a null identity, this is the
[email protected]3f918782009-02-28 01:29:242794 // request we should be issuing -- the final header line contains a Type
2795 // 1 message.
2796 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2797 "Host: 172.22.68.17\r\n"
2798 "Connection: keep-alive\r\n"
2799 "Authorization: NTLM "
2800 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2801
2802 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2803 // (the credentials for the origin server). The second request continues
2804 // on the same connection.
2805 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2806 "Host: 172.22.68.17\r\n"
2807 "Connection: keep-alive\r\n"
[email protected]385a4672009-03-11 22:21:292808 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2809 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2810 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBVKW"
2811 "Yma5xzVAAAAAAAAAAAAAAAAAAAAACH+gWcm+YsP9Tqb9zCR3WAeZZX"
2812 "ahlhx5I=\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242813 };
2814
2815 MockRead data_reads2[] = {
2816 // The origin server responds with a Type 2 message.
2817 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2818 MockRead("WWW-Authenticate: NTLM "
[email protected]385a4672009-03-11 22:21:292819 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCjGpMpPGlYKkAAAAAAAAAALo"
[email protected]3f918782009-02-28 01:29:242820 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2821 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2822 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2823 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2824 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2825 "BtAAAAAAA=\r\n"),
2826 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362827 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]3f918782009-02-28 01:29:242828 MockRead("You are not authorized to view this page\r\n"),
2829
2830 // Lastly we get the desired content.
2831 MockRead("HTTP/1.1 200 OK\r\n"),
2832 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
2833 MockRead("Content-Length: 13\r\n\r\n"),
2834 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:422835 MockRead(false, OK),
[email protected]3f918782009-02-28 01:29:242836 };
2837
[email protected]31a2bfe2010-02-09 08:03:392838 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
2839 data_writes1, arraysize(data_writes1));
2840 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
2841 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:592842 session_deps.socket_factory.AddSocketDataProvider(&data1);
2843 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]3f918782009-02-28 01:29:242844
2845 TestCompletionCallback callback1;
2846
[email protected]0b0bf032010-09-21 18:08:502847 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
2848
[email protected]5a1d7ca2010-04-28 20:12:272849 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:422850 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242851
2852 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422853 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242854
[email protected]0757e7702009-03-27 04:00:222855 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
2856
[email protected]1c773ea12009-04-28 19:58:422857 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:252858 ASSERT_TRUE(response != NULL);
[email protected]3f918782009-02-28 01:29:242859
[email protected]aef04272010-06-28 18:03:042860 // The password prompt info should have been set in
2861 // response->auth_challenge.
[email protected]10af5fe72011-01-31 16:17:252862 ASSERT_FALSE(response->auth_challenge.get() == NULL);
[email protected]3f918782009-02-28 01:29:242863
[email protected]71e4573a2009-05-21 22:03:002864 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]3f918782009-02-28 01:29:242865 EXPECT_EQ(L"", response->auth_challenge->realm);
2866 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
2867
[email protected]10af5fe72011-01-31 16:17:252868 TestCompletionCallback callback2;
2869
2870 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback2);
2871 EXPECT_EQ(ERR_IO_PENDING, rv);
2872
2873 rv = callback2.WaitForResult();
2874 EXPECT_EQ(OK, rv);
2875
2876 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
2877
2878 response = trans->GetResponseInfo();
2879 ASSERT_TRUE(response != NULL);
2880
2881 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2882
[email protected]0757e7702009-03-27 04:00:222883 TestCompletionCallback callback3;
[email protected]3f918782009-02-28 01:29:242884
[email protected]10af5fe72011-01-31 16:17:252885 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:422886 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]3f918782009-02-28 01:29:242887
[email protected]0757e7702009-03-27 04:00:222888 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:422889 EXPECT_EQ(OK, rv);
[email protected]3f918782009-02-28 01:29:242890
2891 response = trans->GetResponseInfo();
[email protected]aef04272010-06-28 18:03:042892 ASSERT_FALSE(response == NULL);
[email protected]3f918782009-02-28 01:29:242893 EXPECT_TRUE(response->auth_challenge.get() == NULL);
2894 EXPECT_EQ(13, response->headers->GetContentLength());
2895}
2896
[email protected]385a4672009-03-11 22:21:292897// Enter a wrong password, and then the correct one.
2898TEST_F(HttpNetworkTransactionTest, NTLMAuth2) {
[email protected]1c773ea12009-04-28 19:58:422899 HttpRequestInfo request;
[email protected]385a4672009-03-11 22:21:292900 request.method = "GET";
2901 request.url = GURL("http://172.22.68.17/kids/login.aspx");
2902 request.load_flags = 0;
2903
[email protected]cb9bf6ca2011-01-28 13:15:272904 HttpAuthHandlerNTLM::ScopedProcSetter proc_setter(MockGenerateRandom2,
2905 MockGetHostName);
2906 SessionDependencies session_deps;
2907 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
2908
[email protected]385a4672009-03-11 22:21:292909 MockWrite data_writes1[] = {
2910 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2911 "Host: 172.22.68.17\r\n"
2912 "Connection: keep-alive\r\n\r\n"),
2913 };
2914
2915 MockRead data_reads1[] = {
2916 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]aef04272010-06-28 18:03:042917 // Negotiate and NTLM are often requested together. However, we only want
2918 // to test NTLM. Since Negotiate is preferred over NTLM, we have to skip
2919 // the header that requests Negotiate for this test.
[email protected]385a4672009-03-11 22:21:292920 MockRead("WWW-Authenticate: NTLM\r\n"),
2921 MockRead("Connection: close\r\n"),
2922 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362923 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292924 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422925 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292926 };
2927
2928 MockWrite data_writes2[] = {
[email protected]0757e7702009-03-27 04:00:222929 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292930 // request we should be issuing -- the final header line contains a Type
2931 // 1 message.
2932 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2933 "Host: 172.22.68.17\r\n"
2934 "Connection: keep-alive\r\n"
2935 "Authorization: NTLM "
2936 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2937
2938 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2939 // (the credentials for the origin server). The second request continues
2940 // on the same connection.
2941 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2942 "Host: 172.22.68.17\r\n"
2943 "Connection: keep-alive\r\n"
2944 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2945 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2946 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwCWeY"
2947 "XnSZNwoQAAAAAAAAAAAAAAAAAAAADLa34/phTTKzNTWdub+uyFleOj"
2948 "4Ww7b7E=\r\n\r\n"),
2949 };
2950
2951 MockRead data_reads2[] = {
2952 // The origin server responds with a Type 2 message.
2953 MockRead("HTTP/1.1 401 Access Denied\r\n"),
2954 MockRead("WWW-Authenticate: NTLM "
2955 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCbVWUZezVGpAAAAAAAAAAALo"
2956 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
2957 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
2958 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
2959 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
2960 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
2961 "BtAAAAAAA=\r\n"),
2962 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362963 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292964 MockRead("You are not authorized to view this page\r\n"),
2965
2966 // Wrong password.
2967 MockRead("HTTP/1.1 401 Access Denied\r\n"),
[email protected]385a4672009-03-11 22:21:292968 MockRead("WWW-Authenticate: NTLM\r\n"),
2969 MockRead("Connection: close\r\n"),
2970 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:362971 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:292972 // Missing content -- won't matter, as connection will be reset.
[email protected]1c773ea12009-04-28 19:58:422973 MockRead(false, ERR_UNEXPECTED),
[email protected]385a4672009-03-11 22:21:292974 };
2975
2976 MockWrite data_writes3[] = {
[email protected]0757e7702009-03-27 04:00:222977 // After restarting with a null identity, this is the
[email protected]385a4672009-03-11 22:21:292978 // request we should be issuing -- the final header line contains a Type
2979 // 1 message.
2980 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2981 "Host: 172.22.68.17\r\n"
2982 "Connection: keep-alive\r\n"
2983 "Authorization: NTLM "
2984 "TlRMTVNTUAABAAAAB4IIAAAAAAAAAAAAAAAAAAAAAAA=\r\n\r\n"),
2985
2986 // After calling trans->RestartWithAuth(), we should send a Type 3 message
2987 // (the credentials for the origin server). The second request continues
2988 // on the same connection.
2989 MockWrite("GET /kids/login.aspx HTTP/1.1\r\n"
2990 "Host: 172.22.68.17\r\n"
2991 "Connection: keep-alive\r\n"
2992 "Authorization: NTLM TlRMTVNTUAADAAAAGAAYAGgAAAAYABgAgA"
2993 "AAAAAAAABAAAAAGAAYAEAAAAAQABAAWAAAAAAAAAAAAAAABYIIAHQA"
2994 "ZQBzAHQAaQBuAGcALQBuAHQAbABtAFcAVABDAC0AVwBJAE4ANwBO54"
2995 "dFMVvTHwAAAAAAAAAAAAAAAAAAAACS7sT6Uzw7L0L//WUqlIaVWpbI"
2996 "+4MUm7c=\r\n\r\n"),
2997 };
2998
2999 MockRead data_reads3[] = {
3000 // The origin server responds with a Type 2 message.
3001 MockRead("HTTP/1.1 401 Access Denied\r\n"),
3002 MockRead("WWW-Authenticate: NTLM "
3003 "TlRMTVNTUAACAAAADAAMADgAAAAFgokCL24VN8dgOR8AAAAAAAAAALo"
3004 "AugBEAAAABQEoCgAAAA9HAE8ATwBHAEwARQACAAwARwBPAE8ARwBMAE"
3005 "UAAQAaAEEASwBFAEUAUwBBAFIAQQAtAEMATwBSAFAABAAeAGMAbwByA"
3006 "HAALgBnAG8AbwBnAGwAZQAuAGMAbwBtAAMAQABhAGsAZQBlAHMAYQBy"
3007 "AGEALQBjAG8AcgBwAC4AYQBkAC4AYwBvAHIAcAAuAGcAbwBvAGcAbAB"
3008 "lAC4AYwBvAG0ABQAeAGMAbwByAHAALgBnAG8AbwBnAGwAZQAuAGMAbw"
3009 "BtAAAAAAA=\r\n"),
3010 MockRead("Content-Length: 42\r\n"),
[email protected]076c85082009-04-10 23:21:363011 MockRead("Content-Type: text/html\r\n\r\n"),
[email protected]385a4672009-03-11 22:21:293012 MockRead("You are not authorized to view this page\r\n"),
3013
3014 // Lastly we get the desired content.
3015 MockRead("HTTP/1.1 200 OK\r\n"),
3016 MockRead("Content-Type: text/html; charset=utf-8\r\n"),
3017 MockRead("Content-Length: 13\r\n\r\n"),
3018 MockRead("Please Login\r\n"),
[email protected]1c773ea12009-04-28 19:58:423019 MockRead(false, OK),
[email protected]385a4672009-03-11 22:21:293020 };
3021
[email protected]31a2bfe2010-02-09 08:03:393022 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3023 data_writes1, arraysize(data_writes1));
3024 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3025 data_writes2, arraysize(data_writes2));
3026 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3027 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593028 session_deps.socket_factory.AddSocketDataProvider(&data1);
3029 session_deps.socket_factory.AddSocketDataProvider(&data2);
3030 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]385a4672009-03-11 22:21:293031
3032 TestCompletionCallback callback1;
3033
[email protected]0b0bf032010-09-21 18:08:503034 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3035
[email protected]5a1d7ca2010-04-28 20:12:273036 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423037 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293038
3039 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423040 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293041
[email protected]0757e7702009-03-27 04:00:223042 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
[email protected]385a4672009-03-11 22:21:293043
[email protected]1c773ea12009-04-28 19:58:423044 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]385a4672009-03-11 22:21:293045 EXPECT_FALSE(response == NULL);
3046
3047 // The password prompt info should have been set in response->auth_challenge.
3048 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3049
[email protected]71e4573a2009-05-21 22:03:003050 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]385a4672009-03-11 22:21:293051 EXPECT_EQ(L"", response->auth_challenge->realm);
3052 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3053
[email protected]10af5fe72011-01-31 16:17:253054 TestCompletionCallback callback2;
[email protected]385a4672009-03-11 22:21:293055
[email protected]0757e7702009-03-27 04:00:223056 // Enter the wrong password.
[email protected]10af5fe72011-01-31 16:17:253057 rv = trans->RestartWithAuth(kTestingNTLM, kWrongPassword, &callback2);
[email protected]1c773ea12009-04-28 19:58:423058 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]385a4672009-03-11 22:21:293059
[email protected]10af5fe72011-01-31 16:17:253060 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423061 EXPECT_EQ(OK, rv);
[email protected]385a4672009-03-11 22:21:293062
[email protected]0757e7702009-03-27 04:00:223063 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
[email protected]10af5fe72011-01-31 16:17:253064 TestCompletionCallback callback3;
3065 rv = trans->RestartWithAuth(string16(), string16(), &callback3);
[email protected]1c773ea12009-04-28 19:58:423066 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]10af5fe72011-01-31 16:17:253067 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423068 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223069 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3070
3071 response = trans->GetResponseInfo();
[email protected]10af5fe72011-01-31 16:17:253072 ASSERT_TRUE(response != NULL);
[email protected]0757e7702009-03-27 04:00:223073
3074 // The password prompt info should have been set in response->auth_challenge.
3075 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3076
[email protected]71e4573a2009-05-21 22:03:003077 EXPECT_EQ(L"172.22.68.17:80", response->auth_challenge->host_and_port);
[email protected]0757e7702009-03-27 04:00:223078 EXPECT_EQ(L"", response->auth_challenge->realm);
3079 EXPECT_EQ(L"ntlm", response->auth_challenge->scheme);
3080
[email protected]10af5fe72011-01-31 16:17:253081 TestCompletionCallback callback4;
[email protected]0757e7702009-03-27 04:00:223082
3083 // Now enter the right password.
[email protected]10af5fe72011-01-31 16:17:253084 rv = trans->RestartWithAuth(kTestingNTLM, kTestingNTLM, &callback4);
3085 EXPECT_EQ(ERR_IO_PENDING, rv);
3086
3087 rv = callback4.WaitForResult();
3088 EXPECT_EQ(OK, rv);
3089
3090 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3091
3092 TestCompletionCallback callback5;
3093
3094 // One more roundtrip
3095 rv = trans->RestartWithAuth(string16(), string16(), &callback5);
[email protected]1c773ea12009-04-28 19:58:423096 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223097
3098 rv = callback5.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423099 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223100
[email protected]385a4672009-03-11 22:21:293101 response = trans->GetResponseInfo();
3102 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3103 EXPECT_EQ(13, response->headers->GetContentLength());
3104}
[email protected]ea9dc9a2009-09-05 00:43:323105#endif // NTLM_PORTABLE
[email protected]385a4672009-03-11 22:21:293106
[email protected]4ddaf2502008-10-23 18:26:193107// Test reading a server response which has only headers, and no body.
3108// After some maximum number of bytes is consumed, the transaction should
3109// fail with ERR_RESPONSE_HEADERS_TOO_BIG.
3110TEST_F(HttpNetworkTransactionTest, LargeHeadersNoBody) {
[email protected]1c773ea12009-04-28 19:58:423111 HttpRequestInfo request;
[email protected]4ddaf2502008-10-23 18:26:193112 request.method = "GET";
3113 request.url = GURL("http://www.google.com/");
3114 request.load_flags = 0;
3115
[email protected]cb9bf6ca2011-01-28 13:15:273116 SessionDependencies session_deps;
3117 scoped_ptr<HttpTransaction> trans(
3118 new HttpNetworkTransaction(CreateSession(&session_deps)));
3119
[email protected]b75b7b2f2009-10-06 00:54:533120 // Respond with 300 kb of headers (we should fail after 256 kb).
[email protected]15a5ccf82008-10-23 19:57:433121 std::string large_headers_string;
[email protected]b75b7b2f2009-10-06 00:54:533122 FillLargeHeadersString(&large_headers_string, 300 * 1024);
[email protected]4ddaf2502008-10-23 18:26:193123
3124 MockRead data_reads[] = {
3125 MockRead("HTTP/1.0 200 OK\r\n"),
[email protected]15a5ccf82008-10-23 19:57:433126 MockRead(true, large_headers_string.data(), large_headers_string.size()),
[email protected]4ddaf2502008-10-23 18:26:193127 MockRead("\r\nBODY"),
[email protected]1c773ea12009-04-28 19:58:423128 MockRead(false, OK),
[email protected]4ddaf2502008-10-23 18:26:193129 };
[email protected]31a2bfe2010-02-09 08:03:393130 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593131 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]4ddaf2502008-10-23 18:26:193132
3133 TestCompletionCallback callback;
3134
[email protected]5a1d7ca2010-04-28 20:12:273135 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423136 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]4ddaf2502008-10-23 18:26:193137
3138 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423139 EXPECT_EQ(ERR_RESPONSE_HEADERS_TOO_BIG, rv);
[email protected]4ddaf2502008-10-23 18:26:193140
[email protected]1c773ea12009-04-28 19:58:423141 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]4ddaf2502008-10-23 18:26:193142 EXPECT_TRUE(response == NULL);
3143}
[email protected]f4e426b2008-11-05 00:24:493144
3145// Make sure that we don't try to reuse a TCPClientSocket when failing to
3146// establish tunnel.
3147// http://code.google.com/p/chromium/issues/detail?id=3772
[email protected]ab739042011-04-07 15:22:283148TEST_F(HttpNetworkTransactionTest, DontRecycleTransportSocketForSSLTunnel) {
[email protected]cb9bf6ca2011-01-28 13:15:273149 HttpRequestInfo request;
3150 request.method = "GET";
3151 request.url = GURL("https://www.google.com/");
3152 request.load_flags = 0;
3153
[email protected]f4e426b2008-11-05 00:24:493154 // Configure against proxy server "myproxy:70".
[email protected]81cdfcd2010-10-16 00:49:003155 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]db8f44c2008-12-13 04:52:013156
[email protected]228ff742009-06-05 01:19:593157 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f4e426b2008-11-05 00:24:493158
[email protected]5695b8c2009-09-30 21:36:433159 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]f4e426b2008-11-05 00:24:493160
[email protected]f4e426b2008-11-05 00:24:493161 // Since we have proxy, should try to establish tunnel.
3162 MockWrite data_writes1[] = {
3163 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:453164 "Host: www.google.com\r\n"
3165 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]f4e426b2008-11-05 00:24:493166 };
3167
[email protected]77848d12008-11-14 00:00:223168 // The proxy responds to the connect with a 404, using a persistent
[email protected]f4e426b2008-11-05 00:24:493169 // connection. Usually a proxy would return 501 (not implemented),
3170 // or 200 (tunnel established).
3171 MockRead data_reads1[] = {
3172 MockRead("HTTP/1.1 404 Not Found\r\n"),
3173 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423174 MockRead(false, ERR_UNEXPECTED), // Should not be reached.
[email protected]f4e426b2008-11-05 00:24:493175 };
3176
[email protected]31a2bfe2010-02-09 08:03:393177 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3178 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593179 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f4e426b2008-11-05 00:24:493180
3181 TestCompletionCallback callback1;
3182
[email protected]5a1d7ca2010-04-28 20:12:273183 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423184 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f4e426b2008-11-05 00:24:493185
3186 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423187 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
[email protected]f4e426b2008-11-05 00:24:493188
[email protected]1c773ea12009-04-28 19:58:423189 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]c744cf22009-02-27 07:28:083190 EXPECT_TRUE(response == NULL);
[email protected]f4e426b2008-11-05 00:24:493191
[email protected]b4404c02009-04-10 16:38:523192 // Empty the current queue. This is necessary because idle sockets are
3193 // added to the connection pool asynchronously with a PostTask.
3194 MessageLoop::current()->RunAllPending();
3195
[email protected]f4e426b2008-11-05 00:24:493196 // We now check to make sure the TCPClientSocket was not added back to
3197 // the pool.
[email protected]ab739042011-04-07 15:22:283198 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493199 trans.reset();
[email protected]b4404c02009-04-10 16:38:523200 MessageLoop::current()->RunAllPending();
[email protected]f4e426b2008-11-05 00:24:493201 // Make sure that the socket didn't get recycled after calling the destructor.
[email protected]ab739042011-04-07 15:22:283202 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]f4e426b2008-11-05 00:24:493203}
[email protected]372d34a2008-11-05 21:30:513204
[email protected]1b157c02009-04-21 01:55:403205// Make sure that we recycle a socket after reading all of the response body.
3206TEST_F(HttpNetworkTransactionTest, RecycleSocket) {
[email protected]1c773ea12009-04-28 19:58:423207 HttpRequestInfo request;
[email protected]1b157c02009-04-21 01:55:403208 request.method = "GET";
3209 request.url = GURL("http://www.google.com/");
3210 request.load_flags = 0;
3211
[email protected]cb9bf6ca2011-01-28 13:15:273212 SessionDependencies session_deps;
3213 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3214
3215 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3216
[email protected]1b157c02009-04-21 01:55:403217 MockRead data_reads[] = {
3218 // A part of the response body is received with the response headers.
3219 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\nhel"),
3220 // The rest of the response body is received in two parts.
3221 MockRead("lo"),
3222 MockRead(" world"),
3223 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423224 MockRead(false, OK),
[email protected]1b157c02009-04-21 01:55:403225 };
3226
[email protected]31a2bfe2010-02-09 08:03:393227 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593228 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1b157c02009-04-21 01:55:403229
3230 TestCompletionCallback callback;
3231
[email protected]5a1d7ca2010-04-28 20:12:273232 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423233 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]1b157c02009-04-21 01:55:403234
3235 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423236 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403237
[email protected]1c773ea12009-04-28 19:58:423238 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]1b157c02009-04-21 01:55:403239 EXPECT_TRUE(response != NULL);
3240
3241 EXPECT_TRUE(response->headers != NULL);
3242 std::string status_line = response->headers->GetStatusLine();
3243 EXPECT_EQ("HTTP/1.1 200 OK", status_line);
3244
[email protected]ab739042011-04-07 15:22:283245 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403246
3247 std::string response_data;
3248 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423249 EXPECT_EQ(OK, rv);
[email protected]1b157c02009-04-21 01:55:403250 EXPECT_EQ("hello world", response_data);
3251
3252 // Empty the current queue. This is necessary because idle sockets are
3253 // added to the connection pool asynchronously with a PostTask.
3254 MessageLoop::current()->RunAllPending();
3255
3256 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283257 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]1b157c02009-04-21 01:55:403258}
3259
[email protected]76a505b2010-08-25 06:23:003260// Make sure that we recycle a SSL socket after reading all of the response
3261// body.
3262TEST_F(HttpNetworkTransactionTest, RecycleSSLSocket) {
3263 SessionDependencies session_deps;
3264 HttpRequestInfo request;
3265 request.method = "GET";
3266 request.url = GURL("https://www.google.com/");
3267 request.load_flags = 0;
3268
3269 MockWrite data_writes[] = {
3270 MockWrite("GET / HTTP/1.1\r\n"
3271 "Host: www.google.com\r\n"
3272 "Connection: keep-alive\r\n\r\n"),
3273 };
3274
3275 MockRead data_reads[] = {
3276 MockRead("HTTP/1.1 200 OK\r\n"),
3277 MockRead("Content-Length: 11\r\n\r\n"),
3278 MockRead("hello world"),
3279 MockRead(false, OK),
3280 };
3281
3282 SSLSocketDataProvider ssl(true, OK);
3283 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3284
3285 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3286 data_writes, arraysize(data_writes));
3287 session_deps.socket_factory.AddSocketDataProvider(&data);
3288
3289 TestCompletionCallback callback;
3290
3291 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3292 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3293
3294 int rv = trans->Start(&request, &callback, BoundNetLog());
3295
3296 EXPECT_EQ(ERR_IO_PENDING, rv);
3297 EXPECT_EQ(OK, callback.WaitForResult());
3298
3299 const HttpResponseInfo* response = trans->GetResponseInfo();
3300 ASSERT_TRUE(response != NULL);
3301 ASSERT_TRUE(response->headers != NULL);
3302 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3303
[email protected]ab739042011-04-07 15:22:283304 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003305
3306 std::string response_data;
3307 rv = ReadTransaction(trans.get(), &response_data);
3308 EXPECT_EQ(OK, rv);
3309 EXPECT_EQ("hello world", response_data);
3310
3311 // Empty the current queue. This is necessary because idle sockets are
3312 // added to the connection pool asynchronously with a PostTask.
3313 MessageLoop::current()->RunAllPending();
3314
3315 // We now check to make sure the socket was added back to the pool.
3316 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3317}
3318
3319// Grab a SSL socket, use it, and put it back into the pool. Then, reuse it
3320// from the pool and make sure that we recover okay.
3321TEST_F(HttpNetworkTransactionTest, RecycleDeadSSLSocket) {
3322 SessionDependencies session_deps;
3323 HttpRequestInfo request;
3324 request.method = "GET";
3325 request.url = GURL("https://www.google.com/");
3326 request.load_flags = 0;
3327
3328 MockWrite data_writes[] = {
3329 MockWrite("GET / HTTP/1.1\r\n"
3330 "Host: www.google.com\r\n"
3331 "Connection: keep-alive\r\n\r\n"),
3332 MockWrite("GET / HTTP/1.1\r\n"
3333 "Host: www.google.com\r\n"
3334 "Connection: keep-alive\r\n\r\n"),
3335 };
3336
3337 MockRead data_reads[] = {
3338 MockRead("HTTP/1.1 200 OK\r\n"),
3339 MockRead("Content-Length: 11\r\n\r\n"),
3340 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
3341 MockRead("hello world"),
3342 MockRead(true, 0, 0) // EOF
3343 };
3344
3345 SSLSocketDataProvider ssl(true, OK);
3346 SSLSocketDataProvider ssl2(true, OK);
3347 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
3348 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl2);
3349
3350 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
3351 data_writes, arraysize(data_writes));
3352 StaticSocketDataProvider data2(data_reads, arraysize(data_reads),
3353 data_writes, arraysize(data_writes));
3354 session_deps.socket_factory.AddSocketDataProvider(&data);
3355 session_deps.socket_factory.AddSocketDataProvider(&data2);
3356
3357 TestCompletionCallback callback;
3358
3359 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3360 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3361
3362 int rv = trans->Start(&request, &callback, BoundNetLog());
3363
3364 EXPECT_EQ(ERR_IO_PENDING, rv);
3365 EXPECT_EQ(OK, callback.WaitForResult());
3366
3367 const HttpResponseInfo* response = trans->GetResponseInfo();
3368 ASSERT_TRUE(response != NULL);
3369 ASSERT_TRUE(response->headers != NULL);
3370 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3371
[email protected]ab739042011-04-07 15:22:283372 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003373
3374 std::string response_data;
3375 rv = ReadTransaction(trans.get(), &response_data);
3376 EXPECT_EQ(OK, rv);
3377 EXPECT_EQ("hello world", response_data);
3378
3379 // Empty the current queue. This is necessary because idle sockets are
3380 // added to the connection pool asynchronously with a PostTask.
3381 MessageLoop::current()->RunAllPending();
3382
3383 // We now check to make sure the socket was added back to the pool.
3384 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3385
3386 // Now start the second transaction, which should reuse the previous socket.
3387
3388 trans.reset(new HttpNetworkTransaction(session));
3389
3390 rv = trans->Start(&request, &callback, BoundNetLog());
3391
3392 EXPECT_EQ(ERR_IO_PENDING, rv);
3393 EXPECT_EQ(OK, callback.WaitForResult());
3394
3395 response = trans->GetResponseInfo();
3396 ASSERT_TRUE(response != NULL);
3397 ASSERT_TRUE(response->headers != NULL);
3398 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3399
[email protected]ab739042011-04-07 15:22:283400 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]76a505b2010-08-25 06:23:003401
3402 rv = ReadTransaction(trans.get(), &response_data);
3403 EXPECT_EQ(OK, rv);
3404 EXPECT_EQ("hello world", response_data);
3405
3406 // Empty the current queue. This is necessary because idle sockets are
3407 // added to the connection pool asynchronously with a PostTask.
3408 MessageLoop::current()->RunAllPending();
3409
3410 // We now check to make sure the socket was added back to the pool.
3411 EXPECT_EQ(1, session->ssl_socket_pool()->IdleSocketCount());
3412}
3413
[email protected]b4404c02009-04-10 16:38:523414// Make sure that we recycle a socket after a zero-length response.
3415// http://crbug.com/9880
3416TEST_F(HttpNetworkTransactionTest, RecycleSocketAfterZeroContentLength) {
[email protected]1c773ea12009-04-28 19:58:423417 HttpRequestInfo request;
[email protected]b4404c02009-04-10 16:38:523418 request.method = "GET";
3419 request.url = GURL("http://www.google.com/csi?v=3&s=web&action=&"
3420 "tran=undefined&ei=mAXcSeegAo-SMurloeUN&"
3421 "e=17259,18167,19592,19773,19981,20133,20173,20233&"
3422 "rt=prt.2642,ol.2649,xjs.2951");
3423 request.load_flags = 0;
3424
[email protected]cb9bf6ca2011-01-28 13:15:273425 SessionDependencies session_deps;
3426 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
3427
3428 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3429
[email protected]b4404c02009-04-10 16:38:523430 MockRead data_reads[] = {
3431 MockRead("HTTP/1.1 204 No Content\r\n"
3432 "Content-Length: 0\r\n"
3433 "Content-Type: text/html\r\n\r\n"),
3434 MockRead("junk"), // Should not be read!!
[email protected]1c773ea12009-04-28 19:58:423435 MockRead(false, OK),
[email protected]b4404c02009-04-10 16:38:523436 };
3437
[email protected]31a2bfe2010-02-09 08:03:393438 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:593439 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]b4404c02009-04-10 16:38:523440
3441 TestCompletionCallback callback;
3442
[email protected]5a1d7ca2010-04-28 20:12:273443 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423444 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]b4404c02009-04-10 16:38:523445
3446 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423447 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523448
[email protected]1c773ea12009-04-28 19:58:423449 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]b4404c02009-04-10 16:38:523450 EXPECT_TRUE(response != NULL);
3451
3452 EXPECT_TRUE(response->headers != NULL);
3453 std::string status_line = response->headers->GetStatusLine();
3454 EXPECT_EQ("HTTP/1.1 204 No Content", status_line);
3455
[email protected]ab739042011-04-07 15:22:283456 EXPECT_EQ(0, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523457
3458 std::string response_data;
3459 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423460 EXPECT_EQ(OK, rv);
[email protected]b4404c02009-04-10 16:38:523461 EXPECT_EQ("", response_data);
3462
3463 // Empty the current queue. This is necessary because idle sockets are
3464 // added to the connection pool asynchronously with a PostTask.
3465 MessageLoop::current()->RunAllPending();
3466
3467 // We now check to make sure the socket was added back to the pool.
[email protected]ab739042011-04-07 15:22:283468 EXPECT_EQ(1, session->transport_socket_pool()->IdleSocketCount());
[email protected]b4404c02009-04-10 16:38:523469}
3470
[email protected]372d34a2008-11-05 21:30:513471TEST_F(HttpNetworkTransactionTest, ResendRequestOnWriteBodyError) {
[email protected]1c773ea12009-04-28 19:58:423472 HttpRequestInfo request[2];
[email protected]372d34a2008-11-05 21:30:513473 // Transaction 1: a GET request that succeeds. The socket is recycled
3474 // after use.
3475 request[0].method = "GET";
3476 request[0].url = GURL("http://www.google.com/");
3477 request[0].load_flags = 0;
3478 // Transaction 2: a POST request. Reuses the socket kept alive from
3479 // transaction 1. The first attempts fails when writing the POST data.
3480 // This causes the transaction to retry with a new socket. The second
3481 // attempt succeeds.
3482 request[1].method = "POST";
3483 request[1].url = GURL("http://www.google.com/login.cgi");
[email protected]1c773ea12009-04-28 19:58:423484 request[1].upload_data = new UploadData;
[email protected]372d34a2008-11-05 21:30:513485 request[1].upload_data->AppendBytes("foo", 3);
3486 request[1].load_flags = 0;
3487
[email protected]228ff742009-06-05 01:19:593488 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273489 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]372d34a2008-11-05 21:30:513490
3491 // The first socket is used for transaction 1 and the first attempt of
3492 // transaction 2.
3493
3494 // The response of transaction 1.
3495 MockRead data_reads1[] = {
3496 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 11\r\n\r\n"),
3497 MockRead("hello world"),
[email protected]1c773ea12009-04-28 19:58:423498 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513499 };
3500 // The mock write results of transaction 1 and the first attempt of
3501 // transaction 2.
3502 MockWrite data_writes1[] = {
3503 MockWrite(false, 64), // GET
3504 MockWrite(false, 93), // POST
[email protected]1c773ea12009-04-28 19:58:423505 MockWrite(false, ERR_CONNECTION_ABORTED), // POST data
[email protected]372d34a2008-11-05 21:30:513506 };
[email protected]31a2bfe2010-02-09 08:03:393507 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3508 data_writes1, arraysize(data_writes1));
[email protected]372d34a2008-11-05 21:30:513509
3510 // The second socket is used for the second attempt of transaction 2.
3511
3512 // The response of transaction 2.
3513 MockRead data_reads2[] = {
3514 MockRead("HTTP/1.1 200 OK\r\nContent-Length: 7\r\n\r\n"),
3515 MockRead("welcome"),
[email protected]1c773ea12009-04-28 19:58:423516 MockRead(false, OK),
[email protected]372d34a2008-11-05 21:30:513517 };
3518 // The mock write results of the second attempt of transaction 2.
3519 MockWrite data_writes2[] = {
3520 MockWrite(false, 93), // POST
3521 MockWrite(false, 3), // POST data
3522 };
[email protected]31a2bfe2010-02-09 08:03:393523 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3524 data_writes2, arraysize(data_writes2));
[email protected]372d34a2008-11-05 21:30:513525
[email protected]5ecc992a42009-11-11 01:41:593526 session_deps.socket_factory.AddSocketDataProvider(&data1);
3527 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]372d34a2008-11-05 21:30:513528
3529 const char* kExpectedResponseData[] = {
3530 "hello world", "welcome"
3531 };
3532
3533 for (int i = 0; i < 2; ++i) {
[email protected]1c773ea12009-04-28 19:58:423534 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:433535 new HttpNetworkTransaction(session));
[email protected]372d34a2008-11-05 21:30:513536
3537 TestCompletionCallback callback;
3538
[email protected]5a1d7ca2010-04-28 20:12:273539 int rv = trans->Start(&request[i], &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423540 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]372d34a2008-11-05 21:30:513541
3542 rv = callback.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423543 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513544
[email protected]1c773ea12009-04-28 19:58:423545 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]372d34a2008-11-05 21:30:513546 EXPECT_TRUE(response != NULL);
3547
3548 EXPECT_TRUE(response->headers != NULL);
3549 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
3550
3551 std::string response_data;
3552 rv = ReadTransaction(trans.get(), &response_data);
[email protected]1c773ea12009-04-28 19:58:423553 EXPECT_EQ(OK, rv);
[email protected]372d34a2008-11-05 21:30:513554 EXPECT_EQ(kExpectedResponseData[i], response_data);
3555 }
3556}
[email protected]f9ee6b52008-11-08 06:46:233557
3558// Test the request-challenge-retry sequence for basic auth when there is
3559// an identity in the URL. The request should be sent as normal, but when
3560// it fails the identity from the URL is used to answer the challenge.
[email protected]ea9dc9a2009-09-05 00:43:323561TEST_F(HttpNetworkTransactionTest, AuthIdentityInURL) {
[email protected]1c773ea12009-04-28 19:58:423562 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233563 request.method = "GET";
3564 // Note: the URL has a username:password in it.
[email protected]a97cca42009-08-14 01:00:293565 request.url = GURL("http://foo:b@[email protected]/");
3566
[email protected]cb9bf6ca2011-01-28 13:15:273567 SessionDependencies session_deps;
3568 scoped_ptr<HttpTransaction> trans(
3569 new HttpNetworkTransaction(CreateSession(&session_deps)));
3570
[email protected]a97cca42009-08-14 01:00:293571 // The password contains an escaped character -- for this test to pass it
3572 // will need to be unescaped by HttpNetworkTransaction.
3573 EXPECT_EQ("b%40r", request.url.password());
3574
[email protected]ea9dc9a2009-09-05 00:43:323575 request.load_flags = LOAD_NORMAL;
[email protected]f9ee6b52008-11-08 06:46:233576
3577 MockWrite data_writes1[] = {
3578 MockWrite("GET / HTTP/1.1\r\n"
3579 "Host: www.google.com\r\n"
3580 "Connection: keep-alive\r\n\r\n"),
3581 };
3582
3583 MockRead data_reads1[] = {
3584 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3585 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3586 MockRead("Content-Length: 10\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423587 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233588 };
3589
3590 // After the challenge above, the transaction will be restarted using the
[email protected]ea9dc9a2009-09-05 00:43:323591 // identity from the url (foo, b@r) to answer the challenge.
[email protected]f9ee6b52008-11-08 06:46:233592 MockWrite data_writes2[] = {
3593 MockWrite("GET / HTTP/1.1\r\n"
3594 "Host: www.google.com\r\n"
3595 "Connection: keep-alive\r\n"
[email protected]a97cca42009-08-14 01:00:293596 "Authorization: Basic Zm9vOmJAcg==\r\n\r\n"),
[email protected]f9ee6b52008-11-08 06:46:233597 };
3598
3599 MockRead data_reads2[] = {
3600 MockRead("HTTP/1.0 200 OK\r\n"),
3601 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423602 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233603 };
3604
[email protected]31a2bfe2010-02-09 08:03:393605 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3606 data_writes1, arraysize(data_writes1));
3607 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3608 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593609 session_deps.socket_factory.AddSocketDataProvider(&data1);
3610 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233611
3612 TestCompletionCallback callback1;
3613
[email protected]5a1d7ca2010-04-28 20:12:273614 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423615 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233616
3617 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423618 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233619
[email protected]0757e7702009-03-27 04:00:223620 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3621 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443622 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:423623 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:223624 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423625 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:223626 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3627
[email protected]1c773ea12009-04-28 19:58:423628 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233629 EXPECT_FALSE(response == NULL);
3630
3631 // There is no challenge info, since the identity in URL worked.
3632 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3633
3634 EXPECT_EQ(100, response->headers->GetContentLength());
3635
3636 // Empty the current queue.
3637 MessageLoop::current()->RunAllPending();
3638}
3639
[email protected]ea9dc9a2009-09-05 00:43:323640// Test the request-challenge-retry sequence for basic auth when there is
3641// an incorrect identity in the URL. The identity from the URL should be used
3642// only once.
3643TEST_F(HttpNetworkTransactionTest, WrongAuthIdentityInURL) {
[email protected]ea9dc9a2009-09-05 00:43:323644 HttpRequestInfo request;
3645 request.method = "GET";
3646 // Note: the URL has a username:password in it. The password "baz" is
3647 // wrong (should be "bar").
3648 request.url = GURL("http://foo:[email protected]/");
3649
3650 request.load_flags = LOAD_NORMAL;
3651
[email protected]cb9bf6ca2011-01-28 13:15:273652 SessionDependencies session_deps;
3653 scoped_ptr<HttpTransaction> trans(
3654 new HttpNetworkTransaction(CreateSession(&session_deps)));
3655
[email protected]ea9dc9a2009-09-05 00:43:323656 MockWrite data_writes1[] = {
3657 MockWrite("GET / HTTP/1.1\r\n"
3658 "Host: www.google.com\r\n"
3659 "Connection: keep-alive\r\n\r\n"),
3660 };
3661
3662 MockRead data_reads1[] = {
3663 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3664 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3665 MockRead("Content-Length: 10\r\n\r\n"),
3666 MockRead(false, ERR_FAILED),
3667 };
3668
3669 // After the challenge above, the transaction will be restarted using the
3670 // identity from the url (foo, baz) to answer the challenge.
3671 MockWrite data_writes2[] = {
3672 MockWrite("GET / HTTP/1.1\r\n"
3673 "Host: www.google.com\r\n"
3674 "Connection: keep-alive\r\n"
3675 "Authorization: Basic Zm9vOmJheg==\r\n\r\n"),
3676 };
3677
3678 MockRead data_reads2[] = {
3679 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3680 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3681 MockRead("Content-Length: 10\r\n\r\n"),
3682 MockRead(false, ERR_FAILED),
3683 };
3684
3685 // After the challenge above, the transaction will be restarted using the
3686 // identity supplied by the user (foo, bar) to answer the challenge.
3687 MockWrite data_writes3[] = {
3688 MockWrite("GET / HTTP/1.1\r\n"
3689 "Host: www.google.com\r\n"
3690 "Connection: keep-alive\r\n"
3691 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3692 };
3693
3694 MockRead data_reads3[] = {
3695 MockRead("HTTP/1.0 200 OK\r\n"),
3696 MockRead("Content-Length: 100\r\n\r\n"),
3697 MockRead(false, OK),
3698 };
3699
[email protected]31a2bfe2010-02-09 08:03:393700 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3701 data_writes1, arraysize(data_writes1));
3702 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3703 data_writes2, arraysize(data_writes2));
3704 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
3705 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:593706 session_deps.socket_factory.AddSocketDataProvider(&data1);
3707 session_deps.socket_factory.AddSocketDataProvider(&data2);
3708 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]ea9dc9a2009-09-05 00:43:323709
3710 TestCompletionCallback callback1;
3711
[email protected]5a1d7ca2010-04-28 20:12:273712 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]ea9dc9a2009-09-05 00:43:323713 EXPECT_EQ(ERR_IO_PENDING, rv);
3714
3715 rv = callback1.WaitForResult();
3716 EXPECT_EQ(OK, rv);
3717
3718 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
3719 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:443720 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]ea9dc9a2009-09-05 00:43:323721 EXPECT_EQ(ERR_IO_PENDING, rv);
3722 rv = callback2.WaitForResult();
3723 EXPECT_EQ(OK, rv);
3724 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3725
3726 const HttpResponseInfo* response = trans->GetResponseInfo();
3727 EXPECT_FALSE(response == NULL);
3728 // The password prompt info should have been set in response->auth_challenge.
3729 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3730
3731 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
3732 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3733 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3734
3735 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:443736 rv = trans->RestartWithAuth(kFoo, kBar, &callback3);
[email protected]ea9dc9a2009-09-05 00:43:323737 EXPECT_EQ(ERR_IO_PENDING, rv);
3738 rv = callback3.WaitForResult();
3739 EXPECT_EQ(OK, rv);
3740 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
3741
3742 response = trans->GetResponseInfo();
3743 EXPECT_FALSE(response == NULL);
3744
3745 // There is no challenge info, since the identity worked.
3746 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3747
3748 EXPECT_EQ(100, response->headers->GetContentLength());
3749
3750 // Empty the current queue.
3751 MessageLoop::current()->RunAllPending();
3752}
3753
[email protected]f9ee6b52008-11-08 06:46:233754// Test that previously tried username/passwords for a realm get re-used.
3755TEST_F(HttpNetworkTransactionTest, BasicAuthCacheAndPreauth) {
[email protected]228ff742009-06-05 01:19:593756 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:273757 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]f9ee6b52008-11-08 06:46:233758
3759 // Transaction 1: authenticate (foo, bar) on MyRealm1
3760 {
[email protected]1c773ea12009-04-28 19:58:423761 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233762 request.method = "GET";
3763 request.url = GURL("http://www.google.com/x/y/z");
3764 request.load_flags = 0;
3765
[email protected]cb9bf6ca2011-01-28 13:15:273766 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3767
[email protected]f9ee6b52008-11-08 06:46:233768 MockWrite data_writes1[] = {
3769 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3770 "Host: www.google.com\r\n"
3771 "Connection: keep-alive\r\n\r\n"),
3772 };
3773
3774 MockRead data_reads1[] = {
3775 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3776 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3777 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423778 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233779 };
3780
3781 // Resend with authorization (username=foo, password=bar)
3782 MockWrite data_writes2[] = {
3783 MockWrite("GET /x/y/z HTTP/1.1\r\n"
3784 "Host: www.google.com\r\n"
3785 "Connection: keep-alive\r\n"
3786 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3787 };
3788
3789 // Sever accepts the authorization.
3790 MockRead data_reads2[] = {
3791 MockRead("HTTP/1.0 200 OK\r\n"),
3792 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423793 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233794 };
3795
[email protected]31a2bfe2010-02-09 08:03:393796 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3797 data_writes1, arraysize(data_writes1));
3798 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3799 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593800 session_deps.socket_factory.AddSocketDataProvider(&data1);
3801 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233802
3803 TestCompletionCallback callback1;
3804
[email protected]5a1d7ca2010-04-28 20:12:273805 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423806 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233807
3808 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423809 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233810
[email protected]1c773ea12009-04-28 19:58:423811 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233812 EXPECT_FALSE(response == NULL);
3813
3814 // The password prompt info should have been set in
3815 // response->auth_challenge.
3816 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3817
[email protected]71e4573a2009-05-21 22:03:003818 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233819 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
3820 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3821
3822 TestCompletionCallback callback2;
3823
[email protected]13c8a092010-07-29 06:15:443824 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]1c773ea12009-04-28 19:58:423825 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233826
3827 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423828 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233829
3830 response = trans->GetResponseInfo();
3831 EXPECT_FALSE(response == NULL);
3832 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3833 EXPECT_EQ(100, response->headers->GetContentLength());
3834 }
3835
3836 // ------------------------------------------------------------------------
3837
3838 // Transaction 2: authenticate (foo2, bar2) on MyRealm2
3839 {
[email protected]1c773ea12009-04-28 19:58:423840 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233841 request.method = "GET";
3842 // Note that Transaction 1 was at /x/y/z, so this is in the same
3843 // protection space as MyRealm1.
3844 request.url = GURL("http://www.google.com/x/y/a/b");
3845 request.load_flags = 0;
3846
[email protected]cb9bf6ca2011-01-28 13:15:273847 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3848
[email protected]f9ee6b52008-11-08 06:46:233849 MockWrite data_writes1[] = {
3850 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3851 "Host: www.google.com\r\n"
3852 "Connection: keep-alive\r\n"
3853 // Send preemptive authorization for MyRealm1
3854 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3855 };
3856
3857 // The server didn't like the preemptive authorization, and
3858 // challenges us for a different realm (MyRealm2).
3859 MockRead data_reads1[] = {
3860 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3861 MockRead("WWW-Authenticate: Basic realm=\"MyRealm2\"\r\n"),
3862 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423863 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233864 };
3865
3866 // Resend with authorization for MyRealm2 (username=foo2, password=bar2)
3867 MockWrite data_writes2[] = {
3868 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
3869 "Host: www.google.com\r\n"
3870 "Connection: keep-alive\r\n"
3871 "Authorization: Basic Zm9vMjpiYXIy\r\n\r\n"),
3872 };
3873
3874 // Sever accepts the authorization.
3875 MockRead data_reads2[] = {
3876 MockRead("HTTP/1.0 200 OK\r\n"),
3877 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423878 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233879 };
3880
[email protected]31a2bfe2010-02-09 08:03:393881 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3882 data_writes1, arraysize(data_writes1));
3883 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
3884 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:593885 session_deps.socket_factory.AddSocketDataProvider(&data1);
3886 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:233887
3888 TestCompletionCallback callback1;
3889
[email protected]5a1d7ca2010-04-28 20:12:273890 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423891 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233892
3893 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423894 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233895
[email protected]1c773ea12009-04-28 19:58:423896 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233897 EXPECT_FALSE(response == NULL);
3898
3899 // The password prompt info should have been set in
3900 // response->auth_challenge.
3901 EXPECT_FALSE(response->auth_challenge.get() == NULL);
3902
[email protected]71e4573a2009-05-21 22:03:003903 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:233904 EXPECT_EQ(L"MyRealm2", response->auth_challenge->realm);
3905 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
3906
3907 TestCompletionCallback callback2;
3908
[email protected]13c8a092010-07-29 06:15:443909 rv = trans->RestartWithAuth(kFoo2, kBar2, &callback2);
[email protected]1c773ea12009-04-28 19:58:423910 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233911
3912 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423913 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233914
3915 response = trans->GetResponseInfo();
3916 EXPECT_FALSE(response == NULL);
3917 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3918 EXPECT_EQ(100, response->headers->GetContentLength());
3919 }
3920
3921 // ------------------------------------------------------------------------
3922
3923 // Transaction 3: Resend a request in MyRealm's protection space --
3924 // succeed with preemptive authorization.
3925 {
[email protected]1c773ea12009-04-28 19:58:423926 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233927 request.method = "GET";
3928 request.url = GURL("http://www.google.com/x/y/z2");
3929 request.load_flags = 0;
3930
[email protected]cb9bf6ca2011-01-28 13:15:273931 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3932
[email protected]f9ee6b52008-11-08 06:46:233933 MockWrite data_writes1[] = {
3934 MockWrite("GET /x/y/z2 HTTP/1.1\r\n"
3935 "Host: www.google.com\r\n"
3936 "Connection: keep-alive\r\n"
3937 // The authorization for MyRealm1 gets sent preemptively
3938 // (since the url is in the same protection space)
3939 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3940 };
3941
3942 // Sever accepts the preemptive authorization
3943 MockRead data_reads1[] = {
3944 MockRead("HTTP/1.0 200 OK\r\n"),
3945 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423946 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:233947 };
3948
[email protected]31a2bfe2010-02-09 08:03:393949 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
3950 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:593951 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]f9ee6b52008-11-08 06:46:233952
3953 TestCompletionCallback callback1;
3954
[email protected]5a1d7ca2010-04-28 20:12:273955 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:423956 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:233957
3958 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:423959 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:233960
[email protected]1c773ea12009-04-28 19:58:423961 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:233962 EXPECT_FALSE(response == NULL);
3963
3964 EXPECT_TRUE(response->auth_challenge.get() == NULL);
3965 EXPECT_EQ(100, response->headers->GetContentLength());
3966 }
3967
3968 // ------------------------------------------------------------------------
3969
3970 // Transaction 4: request another URL in MyRealm (however the
3971 // url is not known to belong to the protection space, so no pre-auth).
3972 {
[email protected]1c773ea12009-04-28 19:58:423973 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:233974 request.method = "GET";
3975 request.url = GURL("http://www.google.com/x/1");
3976 request.load_flags = 0;
3977
[email protected]cb9bf6ca2011-01-28 13:15:273978 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
3979
[email protected]f9ee6b52008-11-08 06:46:233980 MockWrite data_writes1[] = {
3981 MockWrite("GET /x/1 HTTP/1.1\r\n"
3982 "Host: www.google.com\r\n"
3983 "Connection: keep-alive\r\n\r\n"),
3984 };
3985
3986 MockRead data_reads1[] = {
3987 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
3988 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
3989 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:423990 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:233991 };
3992
3993 // Resend with authorization from MyRealm's cache.
3994 MockWrite data_writes2[] = {
3995 MockWrite("GET /x/1 HTTP/1.1\r\n"
3996 "Host: www.google.com\r\n"
3997 "Connection: keep-alive\r\n"
3998 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
3999 };
4000
4001 // Sever accepts the authorization.
4002 MockRead data_reads2[] = {
4003 MockRead("HTTP/1.0 200 OK\r\n"),
4004 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424005 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234006 };
4007
[email protected]31a2bfe2010-02-09 08:03:394008 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4009 data_writes1, arraysize(data_writes1));
4010 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4011 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:594012 session_deps.socket_factory.AddSocketDataProvider(&data1);
4013 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]f9ee6b52008-11-08 06:46:234014
4015 TestCompletionCallback callback1;
4016
[email protected]5a1d7ca2010-04-28 20:12:274017 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424018 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234019
4020 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424021 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234022
[email protected]0757e7702009-03-27 04:00:224023 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4024 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444025 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424026 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224027 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424028 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224029 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4030
[email protected]1c773ea12009-04-28 19:58:424031 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234032 EXPECT_FALSE(response == NULL);
4033 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4034 EXPECT_EQ(100, response->headers->GetContentLength());
4035 }
4036
4037 // ------------------------------------------------------------------------
4038
4039 // Transaction 5: request a URL in MyRealm, but the server rejects the
4040 // cached identity. Should invalidate and re-prompt.
4041 {
[email protected]1c773ea12009-04-28 19:58:424042 HttpRequestInfo request;
[email protected]f9ee6b52008-11-08 06:46:234043 request.method = "GET";
4044 request.url = GURL("http://www.google.com/p/q/t");
4045 request.load_flags = 0;
4046
[email protected]cb9bf6ca2011-01-28 13:15:274047 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4048
[email protected]f9ee6b52008-11-08 06:46:234049 MockWrite data_writes1[] = {
4050 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4051 "Host: www.google.com\r\n"
4052 "Connection: keep-alive\r\n\r\n"),
4053 };
4054
4055 MockRead data_reads1[] = {
4056 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4057 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4058 MockRead("Content-Length: 10000\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424059 MockRead(false, ERR_FAILED),
[email protected]f9ee6b52008-11-08 06:46:234060 };
4061
4062 // Resend with authorization from cache for MyRealm.
4063 MockWrite data_writes2[] = {
4064 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4065 "Host: www.google.com\r\n"
4066 "Connection: keep-alive\r\n"
4067 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
4068 };
4069
4070 // Sever rejects the authorization.
4071 MockRead data_reads2[] = {
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 // At this point we should prompt for new credentials for MyRealm.
4079 // Restart with username=foo3, password=foo4.
4080 MockWrite data_writes3[] = {
4081 MockWrite("GET /p/q/t HTTP/1.1\r\n"
4082 "Host: www.google.com\r\n"
4083 "Connection: keep-alive\r\n"
4084 "Authorization: Basic Zm9vMzpiYXIz\r\n\r\n"),
4085 };
4086
4087 // Sever accepts the authorization.
4088 MockRead data_reads3[] = {
4089 MockRead("HTTP/1.0 200 OK\r\n"),
4090 MockRead("Content-Length: 100\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424091 MockRead(false, OK),
[email protected]f9ee6b52008-11-08 06:46:234092 };
4093
[email protected]31a2bfe2010-02-09 08:03:394094 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4095 data_writes1, arraysize(data_writes1));
4096 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4097 data_writes2, arraysize(data_writes2));
4098 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
4099 data_writes3, arraysize(data_writes3));
[email protected]5ecc992a42009-11-11 01:41:594100 session_deps.socket_factory.AddSocketDataProvider(&data1);
4101 session_deps.socket_factory.AddSocketDataProvider(&data2);
4102 session_deps.socket_factory.AddSocketDataProvider(&data3);
[email protected]f9ee6b52008-11-08 06:46:234103
4104 TestCompletionCallback callback1;
4105
[email protected]5a1d7ca2010-04-28 20:12:274106 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424107 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234108
4109 rv = callback1.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424110 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234111
[email protected]0757e7702009-03-27 04:00:224112 EXPECT_TRUE(trans->IsReadyToRestartForAuth());
4113 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:444114 rv = trans->RestartWithAuth(string16(), string16(), &callback2);
[email protected]1c773ea12009-04-28 19:58:424115 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]0757e7702009-03-27 04:00:224116 rv = callback2.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424117 EXPECT_EQ(OK, rv);
[email protected]0757e7702009-03-27 04:00:224118 EXPECT_FALSE(trans->IsReadyToRestartForAuth());
4119
[email protected]1c773ea12009-04-28 19:58:424120 const HttpResponseInfo* response = trans->GetResponseInfo();
[email protected]f9ee6b52008-11-08 06:46:234121 EXPECT_FALSE(response == NULL);
4122
4123 // The password prompt info should have been set in
4124 // response->auth_challenge.
4125 EXPECT_FALSE(response->auth_challenge.get() == NULL);
4126
[email protected]71e4573a2009-05-21 22:03:004127 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
[email protected]f9ee6b52008-11-08 06:46:234128 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
4129 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
4130
[email protected]0757e7702009-03-27 04:00:224131 TestCompletionCallback callback3;
[email protected]f9ee6b52008-11-08 06:46:234132
[email protected]13c8a092010-07-29 06:15:444133 rv = trans->RestartWithAuth(kFoo3, kBar3, &callback3);
[email protected]1c773ea12009-04-28 19:58:424134 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]f9ee6b52008-11-08 06:46:234135
[email protected]0757e7702009-03-27 04:00:224136 rv = callback3.WaitForResult();
[email protected]1c773ea12009-04-28 19:58:424137 EXPECT_EQ(OK, rv);
[email protected]f9ee6b52008-11-08 06:46:234138
4139 response = trans->GetResponseInfo();
4140 EXPECT_FALSE(response == NULL);
4141 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4142 EXPECT_EQ(100, response->headers->GetContentLength());
4143 }
4144}
[email protected]89ceba9a2009-03-21 03:46:064145
[email protected]3c32c5f2010-05-18 15:18:124146// Tests that nonce count increments when multiple auth attempts
4147// are started with the same nonce.
4148TEST_F(HttpNetworkTransactionTest, DigestPreAuthNonceCount) {
4149 SessionDependencies session_deps;
[email protected]54fea2562010-11-17 14:40:444150 HttpAuthHandlerDigest::Factory* digest_factory =
4151 new HttpAuthHandlerDigest::Factory();
4152 HttpAuthHandlerDigest::FixedNonceGenerator* nonce_generator =
4153 new HttpAuthHandlerDigest::FixedNonceGenerator("0123456789abcdef");
4154 digest_factory->set_nonce_generator(nonce_generator);
4155 session_deps.http_auth_handler_factory.reset(digest_factory);
[email protected]ad8e04a2010-11-01 04:16:274156 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]3c32c5f2010-05-18 15:18:124157
4158 // Transaction 1: authenticate (foo, bar) on MyRealm1
4159 {
[email protected]3c32c5f2010-05-18 15:18:124160 HttpRequestInfo request;
4161 request.method = "GET";
4162 request.url = GURL("http://www.google.com/x/y/z");
4163 request.load_flags = 0;
4164
[email protected]cb9bf6ca2011-01-28 13:15:274165 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4166
[email protected]3c32c5f2010-05-18 15:18:124167 MockWrite data_writes1[] = {
4168 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4169 "Host: www.google.com\r\n"
4170 "Connection: keep-alive\r\n\r\n"),
4171 };
4172
4173 MockRead data_reads1[] = {
4174 MockRead("HTTP/1.0 401 Unauthorized\r\n"),
4175 MockRead("WWW-Authenticate: Digest realm=\"digestive\", nonce=\"OU812\", "
4176 "algorithm=MD5, qop=\"auth\"\r\n\r\n"),
4177 MockRead(false, OK),
4178 };
4179
4180 // Resend with authorization (username=foo, password=bar)
4181 MockWrite data_writes2[] = {
4182 MockWrite("GET /x/y/z HTTP/1.1\r\n"
4183 "Host: www.google.com\r\n"
4184 "Connection: keep-alive\r\n"
4185 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4186 "nonce=\"OU812\", uri=\"/x/y/z\", algorithm=MD5, "
4187 "response=\"03ffbcd30add722589c1de345d7a927f\", qop=auth, "
4188 "nc=00000001, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4189 };
4190
4191 // Sever accepts the authorization.
4192 MockRead data_reads2[] = {
4193 MockRead("HTTP/1.0 200 OK\r\n"),
4194 MockRead(false, OK),
4195 };
4196
4197 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4198 data_writes1, arraysize(data_writes1));
4199 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
4200 data_writes2, arraysize(data_writes2));
4201 session_deps.socket_factory.AddSocketDataProvider(&data1);
4202 session_deps.socket_factory.AddSocketDataProvider(&data2);
4203
4204 TestCompletionCallback callback1;
4205
4206 int rv = trans->Start(&request, &callback1, BoundNetLog());
4207 EXPECT_EQ(ERR_IO_PENDING, rv);
4208
4209 rv = callback1.WaitForResult();
4210 EXPECT_EQ(OK, rv);
4211
4212 const HttpResponseInfo* response = trans->GetResponseInfo();
4213 ASSERT_FALSE(response == NULL);
4214
4215 // The password prompt info should have been set in
4216 // response->auth_challenge.
4217 ASSERT_FALSE(response->auth_challenge.get() == NULL);
4218
4219 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
4220 EXPECT_EQ(L"digestive", response->auth_challenge->realm);
4221 EXPECT_EQ(L"digest", response->auth_challenge->scheme);
4222
4223 TestCompletionCallback callback2;
4224
[email protected]13c8a092010-07-29 06:15:444225 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]3c32c5f2010-05-18 15:18:124226 EXPECT_EQ(ERR_IO_PENDING, rv);
4227
4228 rv = callback2.WaitForResult();
4229 EXPECT_EQ(OK, rv);
4230
4231 response = trans->GetResponseInfo();
4232 ASSERT_FALSE(response == NULL);
4233 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4234 }
4235
4236 // ------------------------------------------------------------------------
4237
4238 // Transaction 2: Request another resource in digestive's protection space.
4239 // This will preemptively add an Authorization header which should have an
4240 // "nc" value of 2 (as compared to 1 in the first use.
4241 {
[email protected]3c32c5f2010-05-18 15:18:124242 HttpRequestInfo request;
4243 request.method = "GET";
4244 // Note that Transaction 1 was at /x/y/z, so this is in the same
4245 // protection space as digest.
4246 request.url = GURL("http://www.google.com/x/y/a/b");
4247 request.load_flags = 0;
4248
[email protected]cb9bf6ca2011-01-28 13:15:274249 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
4250
[email protected]3c32c5f2010-05-18 15:18:124251 MockWrite data_writes1[] = {
4252 MockWrite("GET /x/y/a/b HTTP/1.1\r\n"
4253 "Host: www.google.com\r\n"
4254 "Connection: keep-alive\r\n"
4255 "Authorization: Digest username=\"foo\", realm=\"digestive\", "
4256 "nonce=\"OU812\", uri=\"/x/y/a/b\", algorithm=MD5, "
4257 "response=\"d6f9a2c07d1c5df7b89379dca1269b35\", qop=auth, "
4258 "nc=00000002, cnonce=\"0123456789abcdef\"\r\n\r\n"),
4259 };
4260
4261 // Sever accepts the authorization.
4262 MockRead data_reads1[] = {
4263 MockRead("HTTP/1.0 200 OK\r\n"),
4264 MockRead("Content-Length: 100\r\n\r\n"),
4265 MockRead(false, OK),
4266 };
4267
4268 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
4269 data_writes1, arraysize(data_writes1));
4270 session_deps.socket_factory.AddSocketDataProvider(&data1);
4271
4272 TestCompletionCallback callback1;
4273
4274 int rv = trans->Start(&request, &callback1, BoundNetLog());
4275 EXPECT_EQ(ERR_IO_PENDING, rv);
4276
4277 rv = callback1.WaitForResult();
4278 EXPECT_EQ(OK, rv);
4279
4280 const HttpResponseInfo* response = trans->GetResponseInfo();
4281 ASSERT_FALSE(response == NULL);
4282 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4283 }
4284}
4285
[email protected]89ceba9a2009-03-21 03:46:064286// Test the ResetStateForRestart() private method.
4287TEST_F(HttpNetworkTransactionTest, ResetStateForRestart) {
4288 // Create a transaction (the dependencies aren't important).
[email protected]228ff742009-06-05 01:19:594289 SessionDependencies session_deps;
[email protected]d207a5f2009-06-04 05:28:404290 scoped_ptr<HttpNetworkTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434291 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]89ceba9a2009-03-21 03:46:064292
4293 // Setup some state (which we expect ResetStateForRestart() will clear).
[email protected]89ceba9a2009-03-21 03:46:064294 trans->read_buf_ = new IOBuffer(15);
4295 trans->read_buf_len_ = 15;
[email protected]b94f92d2010-10-27 16:45:204296 trans->request_headers_.SetHeader("Authorization", "NTLM");
[email protected]89ceba9a2009-03-21 03:46:064297
4298 // Setup state in response_
[email protected]a7e41312009-12-16 23:18:144299 HttpResponseInfo* response = &trans->response_;
[email protected]0877e3d2009-10-17 22:29:574300 response->auth_challenge = new AuthChallengeInfo();
4301 response->ssl_info.cert_status = -15;
4302 response->response_time = base::Time::Now();
4303 response->was_cached = true; // (Wouldn't ever actually be true...)
[email protected]89ceba9a2009-03-21 03:46:064304
4305 { // Setup state for response_.vary_data
4306 HttpRequestInfo request;
4307 std::string temp("HTTP/1.1 200 OK\nVary: foo, bar\n\n");
4308 std::replace(temp.begin(), temp.end(), '\n', '\0');
[email protected]ad8e04a2010-11-01 04:16:274309 scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(temp));
[email protected]8c76ae22010-04-20 22:15:434310 request.extra_headers.SetHeader("Foo", "1");
4311 request.extra_headers.SetHeader("bar", "23");
[email protected]0877e3d2009-10-17 22:29:574312 EXPECT_TRUE(response->vary_data.Init(request, *headers));
[email protected]89ceba9a2009-03-21 03:46:064313 }
4314
4315 // Cause the above state to be reset.
4316 trans->ResetStateForRestart();
4317
4318 // Verify that the state that needed to be reset, has been reset.
[email protected]9b6fee12009-09-29 18:13:074319 EXPECT_TRUE(trans->read_buf_.get() == NULL);
[email protected]89ceba9a2009-03-21 03:46:064320 EXPECT_EQ(0, trans->read_buf_len_);
[email protected]b94f92d2010-10-27 16:45:204321 EXPECT_TRUE(trans->request_headers_.IsEmpty());
[email protected]0877e3d2009-10-17 22:29:574322 EXPECT_TRUE(response->auth_challenge.get() == NULL);
4323 EXPECT_TRUE(response->headers.get() == NULL);
[email protected]34f40942010-10-04 00:34:044324 EXPECT_FALSE(response->was_cached);
[email protected]0877e3d2009-10-17 22:29:574325 EXPECT_EQ(0, response->ssl_info.cert_status);
4326 EXPECT_FALSE(response->vary_data.is_valid());
[email protected]89ceba9a2009-03-21 03:46:064327}
4328
[email protected]bacff652009-03-31 17:50:334329// Test HTTPS connections to a site with a bad certificate
4330TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificate) {
[email protected]bacff652009-03-31 17:50:334331 HttpRequestInfo request;
4332 request.method = "GET";
4333 request.url = GURL("https://www.google.com/");
4334 request.load_flags = 0;
4335
[email protected]cb9bf6ca2011-01-28 13:15:274336 SessionDependencies session_deps;
4337 scoped_ptr<HttpTransaction> trans(
4338 new HttpNetworkTransaction(CreateSession(&session_deps)));
4339
[email protected]bacff652009-03-31 17:50:334340 MockWrite data_writes[] = {
4341 MockWrite("GET / HTTP/1.1\r\n"
4342 "Host: www.google.com\r\n"
4343 "Connection: keep-alive\r\n\r\n"),
4344 };
4345
4346 MockRead data_reads[] = {
4347 MockRead("HTTP/1.0 200 OK\r\n"),
4348 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4349 MockRead("Content-Length: 100\r\n\r\n"),
4350 MockRead(false, OK),
4351 };
4352
[email protected]5ecc992a42009-11-11 01:41:594353 StaticSocketDataProvider ssl_bad_certificate;
[email protected]31a2bfe2010-02-09 08:03:394354 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4355 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594356 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4357 SSLSocketDataProvider ssl(true, OK);
[email protected]bacff652009-03-31 17:50:334358
[email protected]5ecc992a42009-11-11 01:41:594359 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4360 session_deps.socket_factory.AddSocketDataProvider(&data);
4361 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4362 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]bacff652009-03-31 17:50:334363
4364 TestCompletionCallback callback;
4365
[email protected]5a1d7ca2010-04-28 20:12:274366 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334367 EXPECT_EQ(ERR_IO_PENDING, rv);
4368
4369 rv = callback.WaitForResult();
4370 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4371
4372 rv = trans->RestartIgnoringLastError(&callback);
4373 EXPECT_EQ(ERR_IO_PENDING, rv);
4374
4375 rv = callback.WaitForResult();
4376 EXPECT_EQ(OK, rv);
4377
4378 const HttpResponseInfo* response = trans->GetResponseInfo();
4379
4380 EXPECT_FALSE(response == NULL);
4381 EXPECT_EQ(100, response->headers->GetContentLength());
4382}
4383
4384// Test HTTPS connections to a site with a bad certificate, going through a
4385// proxy
4386TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaProxy) {
[email protected]81cdfcd2010-10-16 00:49:004387 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]bacff652009-03-31 17:50:334388
4389 HttpRequestInfo request;
4390 request.method = "GET";
4391 request.url = GURL("https://www.google.com/");
4392 request.load_flags = 0;
4393
4394 MockWrite proxy_writes[] = {
4395 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454396 "Host: www.google.com\r\n"
4397 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334398 };
4399
4400 MockRead proxy_reads[] = {
4401 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
[email protected]1c773ea12009-04-28 19:58:424402 MockRead(false, OK)
[email protected]bacff652009-03-31 17:50:334403 };
4404
4405 MockWrite data_writes[] = {
4406 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
[email protected]e44de5d2009-06-05 20:12:454407 "Host: www.google.com\r\n"
4408 "Proxy-Connection: keep-alive\r\n\r\n"),
[email protected]bacff652009-03-31 17:50:334409 MockWrite("GET / HTTP/1.1\r\n"
4410 "Host: www.google.com\r\n"
4411 "Connection: keep-alive\r\n\r\n"),
4412 };
4413
4414 MockRead data_reads[] = {
4415 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4416 MockRead("HTTP/1.0 200 OK\r\n"),
4417 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4418 MockRead("Content-Length: 100\r\n\r\n"),
4419 MockRead(false, OK),
4420 };
4421
[email protected]31a2bfe2010-02-09 08:03:394422 StaticSocketDataProvider ssl_bad_certificate(
4423 proxy_reads, arraysize(proxy_reads),
4424 proxy_writes, arraysize(proxy_writes));
4425 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
4435 TestCompletionCallback callback;
4436
4437 for (int i = 0; i < 2; i++) {
[email protected]228ff742009-06-05 01:19:594438 session_deps.socket_factory.ResetNextMockIndexes();
[email protected]bacff652009-03-31 17:50:334439
[email protected]d207a5f2009-06-04 05:28:404440 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:434441 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]bacff652009-03-31 17:50:334442
[email protected]5a1d7ca2010-04-28 20:12:274443 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]bacff652009-03-31 17:50:334444 EXPECT_EQ(ERR_IO_PENDING, rv);
4445
4446 rv = callback.WaitForResult();
4447 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4448
4449 rv = trans->RestartIgnoringLastError(&callback);
4450 EXPECT_EQ(ERR_IO_PENDING, rv);
4451
4452 rv = callback.WaitForResult();
4453 EXPECT_EQ(OK, rv);
4454
4455 const HttpResponseInfo* response = trans->GetResponseInfo();
4456
4457 EXPECT_FALSE(response == NULL);
4458 EXPECT_EQ(100, response->headers->GetContentLength());
4459 }
4460}
4461
[email protected]2df19bb2010-08-25 20:13:464462
4463// Test HTTPS connections to a site, going through an HTTPS proxy
4464TEST_F(HttpNetworkTransactionTest, HTTPSViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004465 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464466
4467 HttpRequestInfo request;
4468 request.method = "GET";
4469 request.url = GURL("https://www.google.com/");
4470 request.load_flags = 0;
4471
4472 MockWrite data_writes[] = {
4473 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4474 "Host: www.google.com\r\n"
4475 "Proxy-Connection: keep-alive\r\n\r\n"),
4476 MockWrite("GET / HTTP/1.1\r\n"
4477 "Host: www.google.com\r\n"
4478 "Connection: keep-alive\r\n\r\n"),
4479 };
4480
4481 MockRead data_reads[] = {
4482 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4483 MockRead("HTTP/1.1 200 OK\r\n"),
4484 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4485 MockRead("Content-Length: 100\r\n\r\n"),
4486 MockRead(false, OK),
4487 };
4488
4489 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4490 data_writes, arraysize(data_writes));
4491 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4492 SSLSocketDataProvider tunnel_ssl(true, OK); // SSL through the tunnel
4493
4494 session_deps.socket_factory.AddSocketDataProvider(&data);
4495 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4496 session_deps.socket_factory.AddSSLSocketDataProvider(&tunnel_ssl);
4497
4498 TestCompletionCallback callback;
4499
4500 scoped_ptr<HttpTransaction> trans(
4501 new HttpNetworkTransaction(CreateSession(&session_deps)));
4502
4503 int rv = trans->Start(&request, &callback, BoundNetLog());
4504 EXPECT_EQ(ERR_IO_PENDING, rv);
4505
4506 rv = callback.WaitForResult();
4507 EXPECT_EQ(OK, rv);
4508 const HttpResponseInfo* response = trans->GetResponseInfo();
4509
4510 ASSERT_FALSE(response == NULL);
4511
4512 EXPECT_TRUE(response->headers->IsKeepAlive());
4513 EXPECT_EQ(200, response->headers->response_code());
4514 EXPECT_EQ(100, response->headers->GetContentLength());
4515 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4516}
4517
[email protected]511f6f52010-12-17 03:58:294518// Test an HTTPS Proxy's ability to redirect a CONNECT request
4519TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaHttpsProxy) {
4520 SessionDependencies session_deps(
4521 ProxyService::CreateFixed("https://proxy:70"));
4522
4523 HttpRequestInfo request;
4524 request.method = "GET";
4525 request.url = GURL("https://www.google.com/");
4526 request.load_flags = 0;
4527
4528 MockWrite data_writes[] = {
4529 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4530 "Host: www.google.com\r\n"
4531 "Proxy-Connection: keep-alive\r\n\r\n"),
4532 };
4533
4534 MockRead data_reads[] = {
4535 MockRead("HTTP/1.1 302 Redirect\r\n"),
4536 MockRead("Location: http://login.example.com/\r\n"),
4537 MockRead("Content-Length: 0\r\n\r\n"),
4538 MockRead(false, OK),
4539 };
4540
4541 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4542 data_writes, arraysize(data_writes));
4543 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4544
4545 session_deps.socket_factory.AddSocketDataProvider(&data);
4546 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4547
4548 TestCompletionCallback callback;
4549
4550 scoped_ptr<HttpTransaction> trans(
4551 new HttpNetworkTransaction(CreateSession(&session_deps)));
4552
4553 int rv = trans->Start(&request, &callback, BoundNetLog());
4554 EXPECT_EQ(ERR_IO_PENDING, rv);
4555
4556 rv = callback.WaitForResult();
4557 EXPECT_EQ(OK, rv);
4558 const HttpResponseInfo* response = trans->GetResponseInfo();
4559
4560 ASSERT_FALSE(response == NULL);
4561
4562 EXPECT_EQ(302, response->headers->response_code());
4563 std::string url;
4564 EXPECT_TRUE(response->headers->IsRedirect(&url));
4565 EXPECT_EQ("http://login.example.com/", url);
4566}
4567
4568// Test an HTTPS (SPDY) Proxy's ability to redirect a CONNECT request
4569TEST_F(HttpNetworkTransactionTest, RedirectOfHttpsConnectViaSpdyProxy) {
4570 SessionDependencies session_deps(
4571 ProxyService::CreateFixed("https://proxy:70"));
4572
4573 HttpRequestInfo request;
4574 request.method = "GET";
4575 request.url = GURL("https://www.google.com/");
4576 request.load_flags = 0;
4577
4578 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4579 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4580 MockWrite data_writes[] = {
4581 CreateMockWrite(*conn.get(), 0, false),
4582 };
4583
4584 static const char* const kExtraHeaders[] = {
4585 "location",
4586 "http://login.example.com/",
4587 };
4588 scoped_ptr<spdy::SpdyFrame> resp(
4589 ConstructSpdySynReplyError("302 Redirect", kExtraHeaders,
4590 arraysize(kExtraHeaders)/2, 1));
4591 MockRead data_reads[] = {
4592 CreateMockRead(*resp.get(), 1, false),
4593 MockRead(true, 0, 2), // EOF
4594 };
4595
4596 scoped_refptr<DelayedSocketData> data(
4597 new DelayedSocketData(
4598 1, // wait for one write to finish before reading.
4599 data_reads, arraysize(data_reads),
4600 data_writes, arraysize(data_writes)));
4601 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4602 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4603 proxy_ssl.next_proto = "spdy/2";
4604 proxy_ssl.was_npn_negotiated = true;
4605
4606 session_deps.socket_factory.AddSocketDataProvider(data.get());
4607 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4608
4609 TestCompletionCallback callback;
4610
4611 scoped_ptr<HttpTransaction> trans(
4612 new HttpNetworkTransaction(CreateSession(&session_deps)));
4613
4614 int rv = trans->Start(&request, &callback, BoundNetLog());
4615 EXPECT_EQ(ERR_IO_PENDING, rv);
4616
4617 rv = callback.WaitForResult();
4618 EXPECT_EQ(OK, rv);
4619 const HttpResponseInfo* response = trans->GetResponseInfo();
4620
4621 ASSERT_FALSE(response == NULL);
4622
4623 EXPECT_EQ(302, response->headers->response_code());
4624 std::string url;
4625 EXPECT_TRUE(response->headers->IsRedirect(&url));
4626 EXPECT_EQ("http://login.example.com/", url);
4627}
4628
4629// Test an HTTPS Proxy's ability to provide a response to a CONNECT request
4630TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaHttpsProxy) {
4631 SessionDependencies session_deps(
4632 ProxyService::CreateFixed("https://proxy:70"));
4633
4634 HttpRequestInfo request;
4635 request.method = "GET";
4636 request.url = GURL("https://www.google.com/");
4637 request.load_flags = 0;
4638
4639 MockWrite data_writes[] = {
4640 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4641 "Host: www.google.com\r\n"
4642 "Proxy-Connection: keep-alive\r\n\r\n"),
4643 };
4644
4645 MockRead data_reads[] = {
4646 MockRead("HTTP/1.1 404 Not Found\r\n"),
4647 MockRead("Content-Length: 23\r\n\r\n"),
4648 MockRead("The host does not exist"),
4649 MockRead(false, OK),
4650 };
4651
4652 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4653 data_writes, arraysize(data_writes));
4654 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4655
4656 session_deps.socket_factory.AddSocketDataProvider(&data);
4657 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4658
4659 TestCompletionCallback callback;
4660
4661 scoped_ptr<HttpTransaction> trans(
4662 new HttpNetworkTransaction(CreateSession(&session_deps)));
4663
4664 int rv = trans->Start(&request, &callback, BoundNetLog());
4665 EXPECT_EQ(ERR_IO_PENDING, rv);
4666
4667 rv = callback.WaitForResult();
4668 EXPECT_EQ(OK, rv);
4669 const HttpResponseInfo* response = trans->GetResponseInfo();
4670
4671 ASSERT_FALSE(response == NULL);
4672
4673 EXPECT_EQ(404, response->headers->response_code());
4674 EXPECT_EQ(23, response->headers->GetContentLength());
4675 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
4676 EXPECT_FALSE(response->ssl_info.is_valid());
4677
4678 std::string response_data;
4679 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4680 EXPECT_EQ("The host does not exist", response_data);
4681}
4682
4683// Test an HTTPS (SPDY) Proxy's ability to provide a response to a CONNECT
4684// request
4685TEST_F(HttpNetworkTransactionTest, ErrorResponseTofHttpsConnectViaSpdyProxy) {
4686 SessionDependencies session_deps(
4687 ProxyService::CreateFixed("https://proxy:70"));
4688
4689 HttpRequestInfo request;
4690 request.method = "GET";
4691 request.url = GURL("https://www.google.com/");
4692 request.load_flags = 0;
4693
4694 scoped_ptr<spdy::SpdyFrame> conn(ConstructSpdyConnect(NULL, 0, 1));
4695 scoped_ptr<spdy::SpdyFrame> goaway(ConstructSpdyRstStream(1, spdy::CANCEL));
4696 MockWrite data_writes[] = {
4697 CreateMockWrite(*conn.get(), 0, false),
4698 };
4699
4700 static const char* const kExtraHeaders[] = {
4701 "location",
4702 "http://login.example.com/",
4703 };
4704 scoped_ptr<spdy::SpdyFrame> resp(
4705 ConstructSpdySynReplyError("404 Not Found", kExtraHeaders,
4706 arraysize(kExtraHeaders)/2, 1));
4707 scoped_ptr<spdy::SpdyFrame> body(
4708 ConstructSpdyBodyFrame(1, "The host does not exist", 23, true));
4709 MockRead data_reads[] = {
4710 CreateMockRead(*resp.get(), 1, false),
4711 CreateMockRead(*body.get(), 2, false),
4712 MockRead(true, 0, 3), // EOF
4713 };
4714
4715 scoped_refptr<DelayedSocketData> data(
4716 new DelayedSocketData(
4717 1, // wait for one write to finish before reading.
4718 data_reads, arraysize(data_reads),
4719 data_writes, arraysize(data_writes)));
4720 SSLSocketDataProvider proxy_ssl(true, OK); // SSL to the proxy
4721 proxy_ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
4722 proxy_ssl.next_proto = "spdy/2";
4723 proxy_ssl.was_npn_negotiated = true;
4724
4725 session_deps.socket_factory.AddSocketDataProvider(data.get());
4726 session_deps.socket_factory.AddSSLSocketDataProvider(&proxy_ssl);
4727
4728 TestCompletionCallback callback;
4729
4730 scoped_ptr<HttpTransaction> trans(
4731 new HttpNetworkTransaction(CreateSession(&session_deps)));
4732
4733 int rv = trans->Start(&request, &callback, BoundNetLog());
4734 EXPECT_EQ(ERR_IO_PENDING, rv);
4735
4736 rv = callback.WaitForResult();
4737 EXPECT_EQ(OK, rv);
4738 const HttpResponseInfo* response = trans->GetResponseInfo();
4739
4740 ASSERT_FALSE(response == NULL);
4741
4742 EXPECT_EQ(404, response->headers->response_code());
4743 EXPECT_FALSE(response->ssl_info.is_valid());
4744
4745 std::string response_data;
4746 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
4747 EXPECT_EQ("The host does not exist", response_data);
4748}
4749
[email protected]2df19bb2010-08-25 20:13:464750// Test HTTPS connections to a site with a bad certificate, going through an
4751// HTTPS proxy
4752TEST_F(HttpNetworkTransactionTest, HTTPSBadCertificateViaHttpsProxy) {
[email protected]81cdfcd2010-10-16 00:49:004753 SessionDependencies session_deps(ProxyService::CreateFixed("https://proxy:70"));
[email protected]2df19bb2010-08-25 20:13:464754
4755 HttpRequestInfo request;
4756 request.method = "GET";
4757 request.url = GURL("https://www.google.com/");
4758 request.load_flags = 0;
4759
4760 // Attempt to fetch the URL from a server with a bad cert
4761 MockWrite bad_cert_writes[] = {
4762 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4763 "Host: www.google.com\r\n"
4764 "Proxy-Connection: keep-alive\r\n\r\n"),
4765 };
4766
4767 MockRead bad_cert_reads[] = {
4768 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4769 MockRead(false, OK)
4770 };
4771
4772 // Attempt to fetch the URL with a good cert
4773 MockWrite good_data_writes[] = {
4774 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4775 "Host: www.google.com\r\n"
4776 "Proxy-Connection: keep-alive\r\n\r\n"),
4777 MockWrite("GET / HTTP/1.1\r\n"
4778 "Host: www.google.com\r\n"
4779 "Connection: keep-alive\r\n\r\n"),
4780 };
4781
4782 MockRead good_cert_reads[] = {
4783 MockRead("HTTP/1.0 200 Connected\r\n\r\n"),
4784 MockRead("HTTP/1.0 200 OK\r\n"),
4785 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4786 MockRead("Content-Length: 100\r\n\r\n"),
4787 MockRead(false, OK),
4788 };
4789
4790 StaticSocketDataProvider ssl_bad_certificate(
4791 bad_cert_reads, arraysize(bad_cert_reads),
4792 bad_cert_writes, arraysize(bad_cert_writes));
4793 StaticSocketDataProvider data(good_cert_reads, arraysize(good_cert_reads),
4794 good_data_writes, arraysize(good_data_writes));
4795 SSLSocketDataProvider ssl_bad(true, ERR_CERT_AUTHORITY_INVALID);
4796 SSLSocketDataProvider ssl(true, OK);
4797
4798 // SSL to the proxy, then CONNECT request, then SSL with bad certificate
4799 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4800 session_deps.socket_factory.AddSocketDataProvider(&ssl_bad_certificate);
4801 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_bad);
4802
4803 // SSL to the proxy, then CONNECT request, then valid SSL certificate
4804 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4805 session_deps.socket_factory.AddSocketDataProvider(&data);
4806 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
4807
4808 TestCompletionCallback callback;
4809
4810 scoped_ptr<HttpTransaction> trans(
4811 new HttpNetworkTransaction(CreateSession(&session_deps)));
4812
4813 int rv = trans->Start(&request, &callback, BoundNetLog());
4814 EXPECT_EQ(ERR_IO_PENDING, rv);
4815
4816 rv = callback.WaitForResult();
4817 EXPECT_EQ(ERR_CERT_AUTHORITY_INVALID, rv);
4818
4819 rv = trans->RestartIgnoringLastError(&callback);
4820 EXPECT_EQ(ERR_IO_PENDING, rv);
4821
4822 rv = callback.WaitForResult();
4823 EXPECT_EQ(OK, rv);
4824
4825 const HttpResponseInfo* response = trans->GetResponseInfo();
4826
4827 EXPECT_FALSE(response == NULL);
4828 EXPECT_EQ(100, response->headers->GetContentLength());
4829}
4830
[email protected]1c773ea12009-04-28 19:58:424831TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgent) {
[email protected]1c773ea12009-04-28 19:58:424832 HttpRequestInfo request;
4833 request.method = "GET";
4834 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:434835 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4836 "Chromium Ultra Awesome X Edition");
[email protected]1c773ea12009-04-28 19:58:424837
[email protected]cb9bf6ca2011-01-28 13:15:274838 SessionDependencies session_deps;
4839 scoped_ptr<HttpTransaction> trans(
4840 new HttpNetworkTransaction(CreateSession(&session_deps)));
4841
[email protected]1c773ea12009-04-28 19:58:424842 MockWrite data_writes[] = {
4843 MockWrite("GET / HTTP/1.1\r\n"
4844 "Host: www.google.com\r\n"
4845 "Connection: keep-alive\r\n"
4846 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4847 };
4848
4849 // Lastly, the server responds with the actual content.
4850 MockRead data_reads[] = {
4851 MockRead("HTTP/1.0 200 OK\r\n"),
4852 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4853 MockRead("Content-Length: 100\r\n\r\n"),
4854 MockRead(false, OK),
4855 };
4856
[email protected]31a2bfe2010-02-09 08:03:394857 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4858 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594859 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424860
4861 TestCompletionCallback callback;
4862
[email protected]5a1d7ca2010-04-28 20:12:274863 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424864 EXPECT_EQ(ERR_IO_PENDING, rv);
4865
4866 rv = callback.WaitForResult();
4867 EXPECT_EQ(OK, rv);
4868}
4869
[email protected]da81f132010-08-18 23:39:294870TEST_F(HttpNetworkTransactionTest, BuildRequest_UserAgentOverTunnel) {
[email protected]da81f132010-08-18 23:39:294871 HttpRequestInfo request;
4872 request.method = "GET";
4873 request.url = GURL("https://www.google.com/");
4874 request.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
4875 "Chromium Ultra Awesome X Edition");
4876
[email protected]cb9bf6ca2011-01-28 13:15:274877 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
4878 scoped_ptr<HttpTransaction> trans(
4879 new HttpNetworkTransaction(CreateSession(&session_deps)));
4880
[email protected]da81f132010-08-18 23:39:294881 MockWrite data_writes[] = {
4882 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
4883 "Host: www.google.com\r\n"
4884 "Proxy-Connection: keep-alive\r\n"
4885 "User-Agent: Chromium Ultra Awesome X Edition\r\n\r\n"),
4886 };
4887 MockRead data_reads[] = {
4888 // Return an error, so the transaction stops here (this test isn't
4889 // interested in the rest).
4890 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"),
4891 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
4892 MockRead("Proxy-Connection: close\r\n\r\n"),
4893 };
4894
4895 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4896 data_writes, arraysize(data_writes));
4897 session_deps.socket_factory.AddSocketDataProvider(&data);
4898
4899 TestCompletionCallback callback;
4900
4901 int rv = trans->Start(&request, &callback, BoundNetLog());
4902 EXPECT_EQ(ERR_IO_PENDING, rv);
4903
4904 rv = callback.WaitForResult();
4905 EXPECT_EQ(OK, rv);
4906}
4907
[email protected]1c773ea12009-04-28 19:58:424908TEST_F(HttpNetworkTransactionTest, BuildRequest_Referer) {
[email protected]1c773ea12009-04-28 19:58:424909 HttpRequestInfo request;
4910 request.method = "GET";
4911 request.url = GURL("http://www.google.com/");
4912 request.load_flags = 0;
4913 request.referrer = GURL("http://the.previous.site.com/");
4914
[email protected]cb9bf6ca2011-01-28 13:15:274915 SessionDependencies session_deps;
4916 scoped_ptr<HttpTransaction> trans(
4917 new HttpNetworkTransaction(CreateSession(&session_deps)));
4918
[email protected]1c773ea12009-04-28 19:58:424919 MockWrite data_writes[] = {
4920 MockWrite("GET / HTTP/1.1\r\n"
4921 "Host: www.google.com\r\n"
4922 "Connection: keep-alive\r\n"
4923 "Referer: http://the.previous.site.com/\r\n\r\n"),
4924 };
4925
4926 // Lastly, the server responds with the actual content.
4927 MockRead data_reads[] = {
4928 MockRead("HTTP/1.0 200 OK\r\n"),
4929 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4930 MockRead("Content-Length: 100\r\n\r\n"),
4931 MockRead(false, OK),
4932 };
4933
[email protected]31a2bfe2010-02-09 08:03:394934 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4935 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594936 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424937
4938 TestCompletionCallback callback;
4939
[email protected]5a1d7ca2010-04-28 20:12:274940 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424941 EXPECT_EQ(ERR_IO_PENDING, rv);
4942
4943 rv = callback.WaitForResult();
4944 EXPECT_EQ(OK, rv);
4945}
4946
4947TEST_F(HttpNetworkTransactionTest, BuildRequest_PostContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424948 HttpRequestInfo request;
4949 request.method = "POST";
4950 request.url = GURL("http://www.google.com/");
4951
[email protected]cb9bf6ca2011-01-28 13:15:274952 SessionDependencies session_deps;
4953 scoped_ptr<HttpTransaction> trans(
4954 new HttpNetworkTransaction(CreateSession(&session_deps)));
4955
[email protected]1c773ea12009-04-28 19:58:424956 MockWrite data_writes[] = {
4957 MockWrite("POST / HTTP/1.1\r\n"
4958 "Host: www.google.com\r\n"
4959 "Connection: keep-alive\r\n"
4960 "Content-Length: 0\r\n\r\n"),
4961 };
4962
4963 // Lastly, the server responds with the actual content.
4964 MockRead data_reads[] = {
4965 MockRead("HTTP/1.0 200 OK\r\n"),
4966 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
4967 MockRead("Content-Length: 100\r\n\r\n"),
4968 MockRead(false, OK),
4969 };
4970
[email protected]31a2bfe2010-02-09 08:03:394971 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
4972 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:594973 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:424974
4975 TestCompletionCallback callback;
4976
[email protected]5a1d7ca2010-04-28 20:12:274977 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:424978 EXPECT_EQ(ERR_IO_PENDING, rv);
4979
4980 rv = callback.WaitForResult();
4981 EXPECT_EQ(OK, rv);
4982}
4983
4984TEST_F(HttpNetworkTransactionTest, BuildRequest_PutContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:424985 HttpRequestInfo request;
4986 request.method = "PUT";
4987 request.url = GURL("http://www.google.com/");
4988
[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("PUT / HTTP/1.1\r\n"
4995 "Host: www.google.com\r\n"
4996 "Connection: keep-alive\r\n"
4997 "Content-Length: 0\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
5012 TestCompletionCallback callback;
5013
[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_HeadContentLengthZero) {
[email protected]1c773ea12009-04-28 19:58:425022 HttpRequestInfo request;
5023 request.method = "HEAD";
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("HEAD / 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
5049 TestCompletionCallback callback;
5050
[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_CacheControlNoCache) {
[email protected]1c773ea12009-04-28 19:58:425059 HttpRequestInfo request;
5060 request.method = "GET";
5061 request.url = GURL("http://www.google.com/");
5062 request.load_flags = LOAD_BYPASS_CACHE;
5063
[email protected]cb9bf6ca2011-01-28 13:15:275064 SessionDependencies session_deps;
5065 scoped_ptr<HttpTransaction> trans(
5066 new HttpNetworkTransaction(CreateSession(&session_deps)));
5067
[email protected]1c773ea12009-04-28 19:58:425068 MockWrite data_writes[] = {
5069 MockWrite("GET / HTTP/1.1\r\n"
5070 "Host: www.google.com\r\n"
5071 "Connection: keep-alive\r\n"
5072 "Pragma: no-cache\r\n"
5073 "Cache-Control: no-cache\r\n\r\n"),
5074 };
5075
5076 // Lastly, the server responds with the actual content.
5077 MockRead data_reads[] = {
5078 MockRead("HTTP/1.0 200 OK\r\n"),
5079 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5080 MockRead("Content-Length: 100\r\n\r\n"),
5081 MockRead(false, OK),
5082 };
5083
[email protected]31a2bfe2010-02-09 08:03:395084 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5085 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595086 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425087
5088 TestCompletionCallback callback;
5089
[email protected]5a1d7ca2010-04-28 20:12:275090 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425091 EXPECT_EQ(ERR_IO_PENDING, rv);
5092
5093 rv = callback.WaitForResult();
5094 EXPECT_EQ(OK, rv);
5095}
5096
5097TEST_F(HttpNetworkTransactionTest,
5098 BuildRequest_CacheControlValidateCache) {
[email protected]1c773ea12009-04-28 19:58:425099 HttpRequestInfo request;
5100 request.method = "GET";
5101 request.url = GURL("http://www.google.com/");
5102 request.load_flags = LOAD_VALIDATE_CACHE;
5103
[email protected]cb9bf6ca2011-01-28 13:15:275104 SessionDependencies session_deps;
5105 scoped_ptr<HttpTransaction> trans(
5106 new HttpNetworkTransaction(CreateSession(&session_deps)));
5107
[email protected]1c773ea12009-04-28 19:58:425108 MockWrite data_writes[] = {
5109 MockWrite("GET / HTTP/1.1\r\n"
5110 "Host: www.google.com\r\n"
5111 "Connection: keep-alive\r\n"
5112 "Cache-Control: max-age=0\r\n\r\n"),
5113 };
5114
5115 // Lastly, the server responds with the actual content.
5116 MockRead data_reads[] = {
5117 MockRead("HTTP/1.0 200 OK\r\n"),
5118 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5119 MockRead("Content-Length: 100\r\n\r\n"),
5120 MockRead(false, OK),
5121 };
5122
[email protected]31a2bfe2010-02-09 08:03:395123 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5124 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595125 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425126
5127 TestCompletionCallback callback;
5128
[email protected]5a1d7ca2010-04-28 20:12:275129 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425130 EXPECT_EQ(ERR_IO_PENDING, rv);
5131
5132 rv = callback.WaitForResult();
5133 EXPECT_EQ(OK, rv);
5134}
5135
5136TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeaders) {
[email protected]1c773ea12009-04-28 19:58:425137 HttpRequestInfo request;
5138 request.method = "GET";
5139 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435140 request.extra_headers.SetHeader("FooHeader", "Bar");
[email protected]1c773ea12009-04-28 19:58:425141
[email protected]cb9bf6ca2011-01-28 13:15:275142 SessionDependencies session_deps;
5143 scoped_ptr<HttpTransaction> trans(
5144 new HttpNetworkTransaction(CreateSession(&session_deps)));
5145
[email protected]1c773ea12009-04-28 19:58:425146 MockWrite data_writes[] = {
5147 MockWrite("GET / HTTP/1.1\r\n"
5148 "Host: www.google.com\r\n"
5149 "Connection: keep-alive\r\n"
5150 "FooHeader: Bar\r\n\r\n"),
5151 };
5152
5153 // Lastly, the server responds with the actual content.
5154 MockRead data_reads[] = {
5155 MockRead("HTTP/1.0 200 OK\r\n"),
5156 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5157 MockRead("Content-Length: 100\r\n\r\n"),
5158 MockRead(false, OK),
5159 };
5160
[email protected]31a2bfe2010-02-09 08:03:395161 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5162 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595163 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]1c773ea12009-04-28 19:58:425164
5165 TestCompletionCallback callback;
5166
[email protected]5a1d7ca2010-04-28 20:12:275167 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]1c773ea12009-04-28 19:58:425168 EXPECT_EQ(ERR_IO_PENDING, rv);
5169
5170 rv = callback.WaitForResult();
5171 EXPECT_EQ(OK, rv);
5172}
5173
[email protected]270c6412010-03-29 22:02:475174TEST_F(HttpNetworkTransactionTest, BuildRequest_ExtraHeadersStripped) {
[email protected]270c6412010-03-29 22:02:475175 HttpRequestInfo request;
5176 request.method = "GET";
5177 request.url = GURL("http://www.google.com/");
[email protected]8c76ae22010-04-20 22:15:435178 request.extra_headers.SetHeader("referer", "www.foo.com");
5179 request.extra_headers.SetHeader("hEllo", "Kitty");
5180 request.extra_headers.SetHeader("FoO", "bar");
[email protected]270c6412010-03-29 22:02:475181
[email protected]cb9bf6ca2011-01-28 13:15:275182 SessionDependencies session_deps;
5183 scoped_ptr<HttpTransaction> trans(
5184 new HttpNetworkTransaction(CreateSession(&session_deps)));
5185
[email protected]270c6412010-03-29 22:02:475186 MockWrite data_writes[] = {
5187 MockWrite("GET / HTTP/1.1\r\n"
5188 "Host: www.google.com\r\n"
5189 "Connection: keep-alive\r\n"
5190 "hEllo: Kitty\r\n"
5191 "FoO: bar\r\n\r\n"),
5192 };
5193
5194 // Lastly, the server responds with the actual content.
5195 MockRead data_reads[] = {
5196 MockRead("HTTP/1.0 200 OK\r\n"),
5197 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5198 MockRead("Content-Length: 100\r\n\r\n"),
5199 MockRead(false, OK),
5200 };
5201
5202 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5203 data_writes, arraysize(data_writes));
5204 session_deps.socket_factory.AddSocketDataProvider(&data);
5205
5206 TestCompletionCallback callback;
5207
[email protected]5a1d7ca2010-04-28 20:12:275208 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]270c6412010-03-29 22:02:475209 EXPECT_EQ(ERR_IO_PENDING, rv);
5210
5211 rv = callback.WaitForResult();
5212 EXPECT_EQ(OK, rv);
5213}
5214
[email protected]3cd17242009-06-23 02:59:025215TEST_F(HttpNetworkTransactionTest, SOCKS4_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275216 HttpRequestInfo request;
5217 request.method = "GET";
5218 request.url = GURL("http://www.google.com/");
5219 request.load_flags = 0;
5220
[email protected]80d6524d2009-08-18 03:58:095221 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005222 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025223
5224 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435225 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025226
[email protected]3cd17242009-06-23 02:59:025227 char write_buffer[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
5228 char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5229
5230 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355231 MockWrite(true, write_buffer, arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025232 MockWrite("GET / HTTP/1.1\r\n"
5233 "Host: www.google.com\r\n"
5234 "Connection: keep-alive\r\n\r\n")
5235 };
5236
5237 MockRead data_reads[] = {
[email protected]5ecc992a42009-11-11 01:41:595238 MockRead(true, read_buffer, arraysize(read_buffer)),
[email protected]3cd17242009-06-23 02:59:025239 MockRead("HTTP/1.0 200 OK\r\n"),
5240 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5241 MockRead("Payload"),
5242 MockRead(false, OK)
5243 };
5244
[email protected]31a2bfe2010-02-09 08:03:395245 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5246 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595247 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025248
5249 TestCompletionCallback callback;
5250
[email protected]5a1d7ca2010-04-28 20:12:275251 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025252 EXPECT_EQ(ERR_IO_PENDING, rv);
5253
5254 rv = callback.WaitForResult();
5255 EXPECT_EQ(OK, rv);
5256
5257 const HttpResponseInfo* response = trans->GetResponseInfo();
5258 EXPECT_FALSE(response == NULL);
5259
5260 std::string response_text;
5261 rv = ReadTransaction(trans.get(), &response_text);
5262 EXPECT_EQ(OK, rv);
5263 EXPECT_EQ("Payload", response_text);
5264}
5265
5266TEST_F(HttpNetworkTransactionTest, SOCKS4_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275267 HttpRequestInfo request;
5268 request.method = "GET";
5269 request.url = GURL("https://www.google.com/");
5270 request.load_flags = 0;
5271
[email protected]80d6524d2009-08-18 03:58:095272 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005273 ProxyService::CreateFixed("socks4://myproxy:1080"));
[email protected]3cd17242009-06-23 02:59:025274
5275 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435276 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]3cd17242009-06-23 02:59:025277
[email protected]3cd17242009-06-23 02:59:025278 unsigned char write_buffer[] = { 0x04, 0x01, 0x01, 0xBB, 127, 0, 0, 1, 0 };
5279 unsigned char read_buffer[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
5280
5281 MockWrite data_writes[] = {
[email protected]e0c27be2009-07-15 13:09:355282 MockWrite(true, reinterpret_cast<char*>(write_buffer),
5283 arraysize(write_buffer)),
[email protected]3cd17242009-06-23 02:59:025284 MockWrite("GET / HTTP/1.1\r\n"
5285 "Host: www.google.com\r\n"
5286 "Connection: keep-alive\r\n\r\n")
5287 };
5288
5289 MockRead data_reads[] = {
[email protected]e0c27be2009-07-15 13:09:355290 MockWrite(true, reinterpret_cast<char*>(read_buffer),
5291 arraysize(read_buffer)),
5292 MockRead("HTTP/1.0 200 OK\r\n"),
5293 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5294 MockRead("Payload"),
5295 MockRead(false, OK)
5296 };
5297
[email protected]31a2bfe2010-02-09 08:03:395298 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5299 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595300 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355301
[email protected]5ecc992a42009-11-11 01:41:595302 SSLSocketDataProvider ssl(true, OK);
5303 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]e0c27be2009-07-15 13:09:355304
5305 TestCompletionCallback callback;
5306
[email protected]5a1d7ca2010-04-28 20:12:275307 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355308 EXPECT_EQ(ERR_IO_PENDING, rv);
5309
5310 rv = callback.WaitForResult();
5311 EXPECT_EQ(OK, rv);
5312
5313 const HttpResponseInfo* response = trans->GetResponseInfo();
5314 EXPECT_FALSE(response == NULL);
5315
5316 std::string response_text;
5317 rv = ReadTransaction(trans.get(), &response_text);
5318 EXPECT_EQ(OK, rv);
5319 EXPECT_EQ("Payload", response_text);
5320}
5321
5322TEST_F(HttpNetworkTransactionTest, SOCKS5_HTTP_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275323 HttpRequestInfo request;
5324 request.method = "GET";
5325 request.url = GURL("http://www.google.com/");
5326 request.load_flags = 0;
5327
[email protected]80d6524d2009-08-18 03:58:095328 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005329 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355330
5331 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435332 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355333
[email protected]e0c27be2009-07-15 13:09:355334 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5335 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375336 const char kSOCKS5OkRequest[] = {
5337 0x05, // Version
5338 0x01, // Command (CONNECT)
5339 0x00, // Reserved.
5340 0x03, // Address type (DOMAINNAME).
5341 0x0E, // Length of domain (14)
5342 // Domain string:
5343 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5344 0x00, 0x50, // 16-bit port (80)
5345 };
[email protected]e0c27be2009-07-15 13:09:355346 const char kSOCKS5OkResponse[] =
5347 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 };
5348
5349 MockWrite data_writes[] = {
5350 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5351 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)),
5352 MockWrite("GET / HTTP/1.1\r\n"
5353 "Host: www.google.com\r\n"
5354 "Connection: keep-alive\r\n\r\n")
5355 };
5356
5357 MockRead data_reads[] = {
5358 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5359 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
5360 MockRead("HTTP/1.0 200 OK\r\n"),
5361 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5362 MockRead("Payload"),
5363 MockRead(false, OK)
5364 };
5365
[email protected]31a2bfe2010-02-09 08:03:395366 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5367 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595368 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]e0c27be2009-07-15 13:09:355369
5370 TestCompletionCallback callback;
5371
[email protected]5a1d7ca2010-04-28 20:12:275372 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]e0c27be2009-07-15 13:09:355373 EXPECT_EQ(ERR_IO_PENDING, rv);
5374
5375 rv = callback.WaitForResult();
5376 EXPECT_EQ(OK, rv);
5377
5378 const HttpResponseInfo* response = trans->GetResponseInfo();
5379 EXPECT_FALSE(response == NULL);
5380
5381 std::string response_text;
5382 rv = ReadTransaction(trans.get(), &response_text);
5383 EXPECT_EQ(OK, rv);
5384 EXPECT_EQ("Payload", response_text);
5385}
5386
5387TEST_F(HttpNetworkTransactionTest, SOCKS5_SSL_GET) {
[email protected]cb9bf6ca2011-01-28 13:15:275388 HttpRequestInfo request;
5389 request.method = "GET";
5390 request.url = GURL("https://www.google.com/");
5391 request.load_flags = 0;
5392
[email protected]80d6524d2009-08-18 03:58:095393 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005394 ProxyService::CreateFixed("socks5://myproxy:1080"));
[email protected]e0c27be2009-07-15 13:09:355395
5396 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435397 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]e0c27be2009-07-15 13:09:355398
[email protected]e0c27be2009-07-15 13:09:355399 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 };
5400 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 };
[email protected]f209dba2009-12-18 00:24:375401 const unsigned char kSOCKS5OkRequest[] = {
5402 0x05, // Version
5403 0x01, // Command (CONNECT)
5404 0x00, // Reserved.
5405 0x03, // Address type (DOMAINNAME).
5406 0x0E, // Length of domain (14)
5407 // Domain string:
5408 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
5409 0x01, 0xBB, // 16-bit port (443)
5410 };
5411
[email protected]e0c27be2009-07-15 13:09:355412 const char kSOCKS5OkResponse[] =
5413 { 0x05, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0x00, 0x00 };
5414
5415 MockWrite data_writes[] = {
5416 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)),
5417 MockWrite(true, reinterpret_cast<const char*>(kSOCKS5OkRequest),
5418 arraysize(kSOCKS5OkRequest)),
5419 MockWrite("GET / HTTP/1.1\r\n"
5420 "Host: www.google.com\r\n"
5421 "Connection: keep-alive\r\n\r\n")
5422 };
5423
5424 MockRead data_reads[] = {
5425 MockWrite(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)),
5426 MockWrite(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)),
[email protected]3cd17242009-06-23 02:59:025427 MockRead("HTTP/1.0 200 OK\r\n"),
5428 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n\r\n"),
5429 MockRead("Payload"),
5430 MockRead(false, OK)
5431 };
5432
[email protected]31a2bfe2010-02-09 08:03:395433 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
5434 data_writes, arraysize(data_writes));
[email protected]5ecc992a42009-11-11 01:41:595435 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3cd17242009-06-23 02:59:025436
[email protected]5ecc992a42009-11-11 01:41:595437 SSLSocketDataProvider ssl(true, OK);
5438 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]3cd17242009-06-23 02:59:025439
5440 TestCompletionCallback callback;
5441
[email protected]5a1d7ca2010-04-28 20:12:275442 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3cd17242009-06-23 02:59:025443 EXPECT_EQ(ERR_IO_PENDING, rv);
5444
5445 rv = callback.WaitForResult();
5446 EXPECT_EQ(OK, rv);
5447
5448 const HttpResponseInfo* response = trans->GetResponseInfo();
5449 EXPECT_FALSE(response == NULL);
5450
5451 std::string response_text;
5452 rv = ReadTransaction(trans.get(), &response_text);
5453 EXPECT_EQ(OK, rv);
5454 EXPECT_EQ("Payload", response_text);
5455}
5456
[email protected]04e5be32009-06-26 20:00:315457// Tests that for connection endpoints the group names are correctly set.
[email protected]2d731a32010-04-29 01:04:065458
5459struct GroupNameTest {
5460 std::string proxy_server;
5461 std::string url;
5462 std::string expected_group_name;
[email protected]e60e47a2010-07-14 03:37:185463 bool ssl;
[email protected]2d731a32010-04-29 01:04:065464};
5465
5466scoped_refptr<HttpNetworkSession> SetupSessionForGroupNameTests(
[email protected]8b114dd72011-03-25 05:33:025467 SessionDependencies* session_deps) {
5468 scoped_refptr<HttpNetworkSession> session(CreateSession(session_deps));
[email protected]2d731a32010-04-29 01:04:065469
5470 HttpAlternateProtocols* alternate_protocols =
5471 session->mutable_alternate_protocols();
5472 alternate_protocols->SetAlternateProtocolFor(
5473 HostPortPair("host.with.alternate", 80), 443,
[email protected]dae22c52010-07-30 02:16:355474 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]2d731a32010-04-29 01:04:065475
5476 return session;
5477}
5478
5479int GroupNameTransactionHelper(
5480 const std::string& url,
5481 const scoped_refptr<HttpNetworkSession>& session) {
[email protected]2d731a32010-04-29 01:04:065482 HttpRequestInfo request;
5483 request.method = "GET";
5484 request.url = GURL(url);
5485 request.load_flags = 0;
5486
[email protected]cb9bf6ca2011-01-28 13:15:275487 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5488
[email protected]2d731a32010-04-29 01:04:065489 TestCompletionCallback callback;
5490
5491 // We do not complete this request, the dtor will clean the transaction up.
5492 return trans->Start(&request, &callback, BoundNetLog());
5493}
5494
5495TEST_F(HttpNetworkTransactionTest, GroupNameForDirectConnections) {
5496 const GroupNameTest tests[] = {
[email protected]04e5be32009-06-26 20:00:315497 {
[email protected]2d731a32010-04-29 01:04:065498 "", // unused
[email protected]04e5be32009-06-26 20:00:315499 "http://www.google.com/direct",
[email protected]2ff8b312010-04-26 22:20:545500 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185501 false,
[email protected]2ff8b312010-04-26 22:20:545502 },
5503 {
[email protected]2d731a32010-04-29 01:04:065504 "", // unused
[email protected]2ff8b312010-04-26 22:20:545505 "http://[2001:1418:13:1::25]/direct",
5506 "[2001:1418:13:1::25]:80",
[email protected]e60e47a2010-07-14 03:37:185507 false,
[email protected]04e5be32009-06-26 20:00:315508 },
[email protected]04e5be32009-06-26 20:00:315509
5510 // SSL Tests
5511 {
[email protected]2d731a32010-04-29 01:04:065512 "", // unused
[email protected]04e5be32009-06-26 20:00:315513 "https://www.google.com/direct_ssl",
[email protected]0e88ad602010-05-04 23:47:025514 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185515 true,
[email protected]04e5be32009-06-26 20:00:315516 },
5517 {
[email protected]2d731a32010-04-29 01:04:065518 "", // unused
5519 "https://[2001:1418:13:1::25]/direct",
[email protected]0e88ad602010-05-04 23:47:025520 "ssl/[2001:1418:13:1::25]:443",
[email protected]e60e47a2010-07-14 03:37:185521 true,
[email protected]04e5be32009-06-26 20:00:315522 },
5523 {
[email protected]2d731a32010-04-29 01:04:065524 "", // unused
[email protected]2ff8b312010-04-26 22:20:545525 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025526 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185527 true,
[email protected]2ff8b312010-04-26 22:20:545528 },
[email protected]2d731a32010-04-29 01:04:065529 };
[email protected]2ff8b312010-04-26 22:20:545530
[email protected]8e6441ca2010-08-19 05:56:385531 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065532
5533 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025534 SessionDependencies session_deps(
5535 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065536 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025537 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065538
5539 HttpNetworkSessionPeer peer(session);
[email protected]ab739042011-04-07 15:22:285540 CaptureGroupNameTransportSocketPool* transport_conn_pool =
5541 new CaptureGroupNameTransportSocketPool(NULL, NULL);
5542 peer.SetTransportSocketPool(transport_conn_pool);
[email protected]2431756e2010-09-29 20:26:135543 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345544 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185545 peer.SetSSLSocketPool(ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065546
5547 EXPECT_EQ(ERR_IO_PENDING,
5548 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185549 if (tests[i].ssl)
5550 EXPECT_EQ(tests[i].expected_group_name,
5551 ssl_conn_pool->last_group_name_received());
5552 else
5553 EXPECT_EQ(tests[i].expected_group_name,
[email protected]ab739042011-04-07 15:22:285554 transport_conn_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065555 }
5556
[email protected]8e6441ca2010-08-19 05:56:385557 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065558}
5559
5560TEST_F(HttpNetworkTransactionTest, GroupNameForHTTPProxyConnections) {
5561 const GroupNameTest tests[] = {
5562 {
5563 "http_proxy",
5564 "http://www.google.com/http_proxy_normal",
5565 "www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185566 false,
[email protected]2d731a32010-04-29 01:04:065567 },
5568
5569 // SSL Tests
5570 {
5571 "http_proxy",
5572 "https://www.google.com/http_connect_ssl",
[email protected]0e88ad602010-05-04 23:47:025573 "ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185574 true,
[email protected]2d731a32010-04-29 01:04:065575 },
[email protected]af3490e2010-10-16 21:02:295576
[email protected]9faeded92010-04-29 20:03:055577 {
5578 "http_proxy",
5579 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025580 "ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185581 true,
[email protected]9faeded92010-04-29 20:03:055582 },
[email protected]2d731a32010-04-29 01:04:065583 };
5584
[email protected]8e6441ca2010-08-19 05:56:385585 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2d731a32010-04-29 01:04:065586
5587 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025588 SessionDependencies session_deps(
5589 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065590 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025591 SetupSessionForGroupNameTests(&session_deps));
[email protected]2d731a32010-04-29 01:04:065592
5593 HttpNetworkSessionPeer peer(session);
5594
[email protected]e60e47a2010-07-14 03:37:185595 HostPortPair proxy_host("http_proxy", 80);
[email protected]2431756e2010-09-29 20:26:135596 CaptureGroupNameHttpProxySocketPool* http_proxy_pool =
[email protected]9e1bdd32011-02-03 21:48:345597 new CaptureGroupNameHttpProxySocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185598 peer.SetSocketPoolForHTTPProxy(proxy_host, http_proxy_pool);
[email protected]2431756e2010-09-29 20:26:135599 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345600 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185601 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]2d731a32010-04-29 01:04:065602
5603 EXPECT_EQ(ERR_IO_PENDING,
5604 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185605 if (tests[i].ssl)
5606 EXPECT_EQ(tests[i].expected_group_name,
5607 ssl_conn_pool->last_group_name_received());
5608 else
5609 EXPECT_EQ(tests[i].expected_group_name,
5610 http_proxy_pool->last_group_name_received());
[email protected]2d731a32010-04-29 01:04:065611 }
5612
[email protected]8e6441ca2010-08-19 05:56:385613 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2d731a32010-04-29 01:04:065614}
5615
5616TEST_F(HttpNetworkTransactionTest, GroupNameForSOCKSConnections) {
5617 const GroupNameTest tests[] = {
5618 {
5619 "socks4://socks_proxy:1080",
5620 "http://www.google.com/socks4_direct",
5621 "socks4/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185622 false,
[email protected]2d731a32010-04-29 01:04:065623 },
5624 {
5625 "socks5://socks_proxy:1080",
5626 "http://www.google.com/socks5_direct",
5627 "socks5/www.google.com:80",
[email protected]e60e47a2010-07-14 03:37:185628 false,
[email protected]2d731a32010-04-29 01:04:065629 },
5630
5631 // SSL Tests
5632 {
5633 "socks4://socks_proxy:1080",
5634 "https://www.google.com/socks4_ssl",
[email protected]0e88ad602010-05-04 23:47:025635 "socks4/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185636 true,
[email protected]2d731a32010-04-29 01:04:065637 },
5638 {
5639 "socks5://socks_proxy:1080",
5640 "https://www.google.com/socks5_ssl",
[email protected]0e88ad602010-05-04 23:47:025641 "socks5/ssl/www.google.com:443",
[email protected]e60e47a2010-07-14 03:37:185642 true,
[email protected]2d731a32010-04-29 01:04:065643 },
[email protected]af3490e2010-10-16 21:02:295644
[email protected]9faeded92010-04-29 20:03:055645 {
5646 "socks4://socks_proxy:1080",
5647 "http://host.with.alternate/direct",
[email protected]0e88ad602010-05-04 23:47:025648 "socks4/ssl/host.with.alternate:443",
[email protected]e60e47a2010-07-14 03:37:185649 true,
[email protected]9faeded92010-04-29 20:03:055650 },
[email protected]04e5be32009-06-26 20:00:315651 };
5652
[email protected]8e6441ca2010-08-19 05:56:385653 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]2ff8b312010-04-26 22:20:545654
[email protected]04e5be32009-06-26 20:00:315655 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
[email protected]8b114dd72011-03-25 05:33:025656 SessionDependencies session_deps(
5657 ProxyService::CreateFixed(tests[i].proxy_server));
[email protected]2d731a32010-04-29 01:04:065658 scoped_refptr<HttpNetworkSession> session(
[email protected]8b114dd72011-03-25 05:33:025659 SetupSessionForGroupNameTests(&session_deps));
5660
[email protected]2d731a32010-04-29 01:04:065661 HttpNetworkSessionPeer peer(session);
[email protected]04e5be32009-06-26 20:00:315662
[email protected]e60e47a2010-07-14 03:37:185663 HostPortPair proxy_host("socks_proxy", 1080);
[email protected]2431756e2010-09-29 20:26:135664 CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345665 new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185666 peer.SetSocketPoolForSOCKSProxy(proxy_host, socks_conn_pool);
[email protected]2431756e2010-09-29 20:26:135667 CaptureGroupNameSSLSocketPool* ssl_conn_pool =
[email protected]9e1bdd32011-02-03 21:48:345668 new CaptureGroupNameSSLSocketPool(NULL, NULL);
[email protected]e60e47a2010-07-14 03:37:185669 peer.SetSocketPoolForSSLWithProxy(proxy_host, ssl_conn_pool);
[email protected]04e5be32009-06-26 20:00:315670
[email protected]5695b8c2009-09-30 21:36:435671 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]04e5be32009-06-26 20:00:315672
[email protected]2d731a32010-04-29 01:04:065673 EXPECT_EQ(ERR_IO_PENDING,
5674 GroupNameTransactionHelper(tests[i].url, session));
[email protected]e60e47a2010-07-14 03:37:185675 if (tests[i].ssl)
5676 EXPECT_EQ(tests[i].expected_group_name,
5677 ssl_conn_pool->last_group_name_received());
5678 else
5679 EXPECT_EQ(tests[i].expected_group_name,
5680 socks_conn_pool->last_group_name_received());
[email protected]04e5be32009-06-26 20:00:315681 }
[email protected]2ff8b312010-04-26 22:20:545682
[email protected]8e6441ca2010-08-19 05:56:385683 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]04e5be32009-06-26 20:00:315684}
5685
[email protected]9172a982009-06-06 00:30:255686TEST_F(HttpNetworkTransactionTest, ReconsiderProxyAfterFailedConnection) {
[email protected]cb9bf6ca2011-01-28 13:15:275687 HttpRequestInfo request;
5688 request.method = "GET";
5689 request.url = GURL("http://www.google.com/");
5690
[email protected]5c6a17e2009-06-10 00:54:545691 SessionDependencies session_deps(
[email protected]81cdfcd2010-10-16 00:49:005692 ProxyService::CreateFixed("myproxy:70;foobar:80"));
[email protected]b59ff372009-07-15 22:04:325693
[email protected]69719062010-01-05 20:09:215694 // This simulates failure resolving all hostnames; that means we will fail
5695 // connecting to both proxies (myproxy:70 and foobar:80).
[email protected]b59ff372009-07-15 22:04:325696 session_deps.host_resolver->rules()->AddSimulatedFailure("*");
5697
[email protected]9172a982009-06-06 00:30:255698 scoped_ptr<HttpTransaction> trans(
[email protected]5695b8c2009-09-30 21:36:435699 new HttpNetworkTransaction(CreateSession(&session_deps)));
[email protected]9172a982009-06-06 00:30:255700
[email protected]9172a982009-06-06 00:30:255701 TestCompletionCallback callback;
5702
[email protected]5a1d7ca2010-04-28 20:12:275703 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9172a982009-06-06 00:30:255704 EXPECT_EQ(ERR_IO_PENDING, rv);
5705
[email protected]9172a982009-06-06 00:30:255706 rv = callback.WaitForResult();
[email protected]f7fccee2010-09-16 20:53:015707 EXPECT_EQ(ERR_PROXY_CONNECTION_FAILED, rv);
[email protected]9172a982009-06-06 00:30:255708}
5709
[email protected]f3e6c1e2009-06-15 20:52:125710// Host resolution observer used by
5711// HttpNetworkTransactionTest.ResolveMadeWithReferrer to check that host
5712// resovle requests are issued with a referrer of |expected_referrer|.
5713class ResolutionReferrerObserver : public HostResolver::Observer {
5714 public:
5715 explicit ResolutionReferrerObserver(const GURL& expected_referrer)
5716 : expected_referrer_(expected_referrer),
5717 called_start_with_referrer_(false),
5718 called_finish_with_referrer_(false) {
5719 }
5720
5721 virtual void OnStartResolution(int id,
5722 const HostResolver::RequestInfo& info) {
5723 if (info.referrer() == expected_referrer_)
5724 called_start_with_referrer_ = true;
5725 }
5726
5727 virtual void OnFinishResolutionWithStatus(
5728 int id, bool was_resolved, const HostResolver::RequestInfo& info ) {
5729 if (info.referrer() == expected_referrer_)
5730 called_finish_with_referrer_ = true;
5731 }
5732
[email protected]eb255d32009-06-17 02:11:035733 virtual void OnCancelResolution(int id,
5734 const HostResolver::RequestInfo& info ) {
5735 FAIL() << "Should not be cancelling any requests!";
5736 }
5737
[email protected]f3e6c1e2009-06-15 20:52:125738 bool did_complete_with_expected_referrer() const {
5739 return called_start_with_referrer_ && called_finish_with_referrer_;
5740 }
5741
5742 private:
5743 GURL expected_referrer_;
5744 bool called_start_with_referrer_;
5745 bool called_finish_with_referrer_;
5746
5747 DISALLOW_COPY_AND_ASSIGN(ResolutionReferrerObserver);
5748};
5749
5750// Make sure that when HostResolver::Resolve() is invoked, it passes through
5751// the "referrer". This is depended on by the DNS prefetch observer.
5752TEST_F(HttpNetworkTransactionTest, ResolveMadeWithReferrer) {
5753 GURL referrer = GURL("http://expected-referrer/");
5754 EXPECT_TRUE(referrer.is_valid());
5755 ResolutionReferrerObserver resolution_observer(referrer);
5756
[email protected]cb9bf6ca2011-01-28 13:15:275757 // Issue a request, containing an HTTP referrer.
5758 HttpRequestInfo request;
5759 request.method = "GET";
5760 request.referrer = referrer;
5761 request.url = GURL("http://www.google.com/");
5762
[email protected]f3e6c1e2009-06-15 20:52:125763 SessionDependencies session_deps;
5764 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435765 CreateSession(&session_deps)));
[email protected]f3e6c1e2009-06-15 20:52:125766
5767 // Attach an observer to watch the host resolutions being made.
[email protected]94a0d3d92009-06-27 01:50:145768 session_deps.host_resolver->AddObserver(&resolution_observer);
[email protected]f3e6c1e2009-06-15 20:52:125769
5770 // Connect up a mock socket which will fail when reading.
5771 MockRead data_reads[] = {
5772 MockRead(false, ERR_FAILED),
5773 };
[email protected]31a2bfe2010-02-09 08:03:395774 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595775 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]f3e6c1e2009-06-15 20:52:125776
[email protected]f3e6c1e2009-06-15 20:52:125777 // Run the request until it fails reading from the socket.
5778 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275779 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]f3e6c1e2009-06-15 20:52:125780 EXPECT_EQ(ERR_IO_PENDING, rv);
5781 rv = callback.WaitForResult();
5782 EXPECT_EQ(ERR_FAILED, rv);
5783
5784 // Check that the host resolution observer saw |referrer|.
5785 EXPECT_TRUE(resolution_observer.did_complete_with_expected_referrer());
5786}
5787
[email protected]685af592010-05-11 19:31:245788// Base test to make sure that when the load flags for a request specify to
5789// bypass the cache, the DNS cache is not used.
5790void BypassHostCacheOnRefreshHelper(int load_flags) {
[email protected]cb9bf6ca2011-01-28 13:15:275791 // Issue a request, asking to bypass the cache(s).
5792 HttpRequestInfo request;
5793 request.method = "GET";
5794 request.load_flags = load_flags;
5795 request.url = GURL("http://www.google.com/");
5796
[email protected]3b9cca42009-06-16 01:08:285797 SessionDependencies session_deps;
[email protected]b59ff372009-07-15 22:04:325798
[email protected]a2c2fb92009-07-18 07:31:045799 // Select a host resolver that does caching.
[email protected]73c45322010-10-01 23:57:545800 session_deps.host_resolver.reset(new MockCachingHostResolver);
[email protected]b59ff372009-07-15 22:04:325801
[email protected]3b9cca42009-06-16 01:08:285802 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(
[email protected]5695b8c2009-09-30 21:36:435803 CreateSession(&session_deps)));
[email protected]3b9cca42009-06-16 01:08:285804
5805 // Warm up the host cache so it has an entry for "www.google.com" (by doing
5806 // a synchronous lookup.)
5807 AddressList addrlist;
[email protected]94a0d3d92009-06-27 01:50:145808 int rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105809 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275810 NULL, NULL, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285811 EXPECT_EQ(OK, rv);
5812
5813 // Verify that it was added to host cache, by doing a subsequent async lookup
5814 // and confirming it completes synchronously.
5815 TestCompletionCallback resolve_callback;
[email protected]684970b2009-08-14 04:54:465816 rv = session_deps.host_resolver->Resolve(
[email protected]930cc742010-09-15 22:54:105817 HostResolver::RequestInfo(HostPortPair("www.google.com", 80)), &addrlist,
[email protected]5a1d7ca2010-04-28 20:12:275818 &resolve_callback, NULL, BoundNetLog());
[email protected]b59ff372009-07-15 22:04:325819 ASSERT_EQ(OK, rv);
[email protected]3b9cca42009-06-16 01:08:285820
5821 // Inject a failure the next time that "www.google.com" is resolved. This way
5822 // we can tell if the next lookup hit the cache, or the "network".
5823 // (cache --> success, "network" --> failure).
[email protected]b59ff372009-07-15 22:04:325824 session_deps.host_resolver->rules()->AddSimulatedFailure("www.google.com");
[email protected]3b9cca42009-06-16 01:08:285825
5826 // Connect up a mock socket which will fail with ERR_UNEXPECTED during the
5827 // first read -- this won't be reached as the host resolution will fail first.
5828 MockRead data_reads[] = { MockRead(false, ERR_UNEXPECTED) };
[email protected]31a2bfe2010-02-09 08:03:395829 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595830 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]3b9cca42009-06-16 01:08:285831
[email protected]3b9cca42009-06-16 01:08:285832 // Run the request.
5833 TestCompletionCallback callback;
[email protected]5a1d7ca2010-04-28 20:12:275834 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]3b9cca42009-06-16 01:08:285835 ASSERT_EQ(ERR_IO_PENDING, rv);
5836 rv = callback.WaitForResult();
5837
5838 // If we bypassed the cache, we would have gotten a failure while resolving
5839 // "www.google.com".
5840 EXPECT_EQ(ERR_NAME_NOT_RESOLVED, rv);
5841}
5842
[email protected]685af592010-05-11 19:31:245843// There are multiple load flags that should trigger the host cache bypass.
5844// Test each in isolation:
5845TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh1) {
5846 BypassHostCacheOnRefreshHelper(LOAD_BYPASS_CACHE);
5847}
5848
5849TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh2) {
5850 BypassHostCacheOnRefreshHelper(LOAD_VALIDATE_CACHE);
5851}
5852
5853TEST_F(HttpNetworkTransactionTest, BypassHostCacheOnRefresh3) {
5854 BypassHostCacheOnRefreshHelper(LOAD_DISABLE_CACHE);
5855}
5856
[email protected]0877e3d2009-10-17 22:29:575857// Make sure we can handle an error when writing the request.
5858TEST_F(HttpNetworkTransactionTest, RequestWriteError) {
5859 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275860 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575861
5862 HttpRequestInfo request;
5863 request.method = "GET";
5864 request.url = GURL("http://www.foo.com/");
5865 request.load_flags = 0;
5866
5867 MockWrite write_failure[] = {
5868 MockWrite(true, ERR_CONNECTION_RESET),
5869 };
[email protected]31a2bfe2010-02-09 08:03:395870 StaticSocketDataProvider data(NULL, 0,
5871 write_failure, arraysize(write_failure));
[email protected]5ecc992a42009-11-11 01:41:595872 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575873
5874 TestCompletionCallback callback;
5875
5876 scoped_ptr<HttpTransaction> trans(
5877 new HttpNetworkTransaction(CreateSession(&session_deps)));
5878
[email protected]5a1d7ca2010-04-28 20:12:275879 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575880 EXPECT_EQ(ERR_IO_PENDING, rv);
5881
5882 rv = callback.WaitForResult();
5883 EXPECT_EQ(ERR_CONNECTION_RESET, rv);
5884}
5885
5886// Check that a connection closed after the start of the headers finishes ok.
5887TEST_F(HttpNetworkTransactionTest, ConnectionClosedAfterStartOfHeaders) {
5888 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275889 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575890
5891 HttpRequestInfo request;
5892 request.method = "GET";
5893 request.url = GURL("http://www.foo.com/");
5894 request.load_flags = 0;
5895
5896 MockRead data_reads[] = {
5897 MockRead("HTTP/1."),
5898 MockRead(false, OK),
5899 };
5900
[email protected]31a2bfe2010-02-09 08:03:395901 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:595902 session_deps.socket_factory.AddSocketDataProvider(&data);
[email protected]0877e3d2009-10-17 22:29:575903
5904 TestCompletionCallback callback;
5905
5906 scoped_ptr<HttpTransaction> trans(
5907 new HttpNetworkTransaction(CreateSession(&session_deps)));
5908
[email protected]5a1d7ca2010-04-28 20:12:275909 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575910 EXPECT_EQ(ERR_IO_PENDING, rv);
5911
5912 rv = callback.WaitForResult();
5913 EXPECT_EQ(OK, rv);
5914
5915 const HttpResponseInfo* response = trans->GetResponseInfo();
5916 EXPECT_TRUE(response != NULL);
5917
5918 EXPECT_TRUE(response->headers != NULL);
5919 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
5920
5921 std::string response_data;
5922 rv = ReadTransaction(trans.get(), &response_data);
5923 EXPECT_EQ(OK, rv);
5924 EXPECT_EQ("", response_data);
5925}
5926
5927// Make sure that a dropped connection while draining the body for auth
5928// restart does the right thing.
5929TEST_F(HttpNetworkTransactionTest, DrainResetOK) {
5930 SessionDependencies session_deps;
[email protected]ad8e04a2010-11-01 04:16:275931 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]0877e3d2009-10-17 22:29:575932
5933 HttpRequestInfo request;
5934 request.method = "GET";
5935 request.url = GURL("http://www.google.com/");
5936 request.load_flags = 0;
5937
5938 MockWrite data_writes1[] = {
5939 MockWrite("GET / HTTP/1.1\r\n"
5940 "Host: www.google.com\r\n"
5941 "Connection: keep-alive\r\n\r\n"),
5942 };
5943
5944 MockRead data_reads1[] = {
5945 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
5946 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
5947 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5948 MockRead("Content-Length: 14\r\n\r\n"),
5949 MockRead("Unauth"),
5950 MockRead(true, ERR_CONNECTION_RESET),
5951 };
5952
[email protected]31a2bfe2010-02-09 08:03:395953 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
5954 data_writes1, arraysize(data_writes1));
[email protected]5ecc992a42009-11-11 01:41:595955 session_deps.socket_factory.AddSocketDataProvider(&data1);
[email protected]0877e3d2009-10-17 22:29:575956
5957 // After calling trans->RestartWithAuth(), this is the request we should
5958 // be issuing -- the final header line contains the credentials.
5959 MockWrite data_writes2[] = {
5960 MockWrite("GET / HTTP/1.1\r\n"
5961 "Host: www.google.com\r\n"
5962 "Connection: keep-alive\r\n"
5963 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
5964 };
5965
5966 // Lastly, the server responds with the actual content.
5967 MockRead data_reads2[] = {
5968 MockRead("HTTP/1.1 200 OK\r\n"),
5969 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
5970 MockRead("Content-Length: 100\r\n\r\n"),
5971 MockRead(false, OK),
5972 };
5973
[email protected]31a2bfe2010-02-09 08:03:395974 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
5975 data_writes2, arraysize(data_writes2));
[email protected]5ecc992a42009-11-11 01:41:595976 session_deps.socket_factory.AddSocketDataProvider(&data2);
[email protected]0877e3d2009-10-17 22:29:575977
5978 TestCompletionCallback callback1;
5979
[email protected]0b0bf032010-09-21 18:08:505980 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
5981
[email protected]5a1d7ca2010-04-28 20:12:275982 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:575983 EXPECT_EQ(ERR_IO_PENDING, rv);
5984
5985 rv = callback1.WaitForResult();
5986 EXPECT_EQ(OK, rv);
5987
5988 const HttpResponseInfo* response = trans->GetResponseInfo();
5989 EXPECT_FALSE(response == NULL);
5990
5991 // The password prompt info should have been set in response->auth_challenge.
5992 EXPECT_FALSE(response->auth_challenge.get() == NULL);
5993
5994 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
5995 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
5996 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
5997
5998 TestCompletionCallback callback2;
5999
[email protected]13c8a092010-07-29 06:15:446000 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]0877e3d2009-10-17 22:29:576001 EXPECT_EQ(ERR_IO_PENDING, rv);
6002
6003 rv = callback2.WaitForResult();
6004 EXPECT_EQ(OK, rv);
6005
6006 response = trans->GetResponseInfo();
6007 EXPECT_FALSE(response == NULL);
6008 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6009 EXPECT_EQ(100, response->headers->GetContentLength());
6010}
6011
6012// Test HTTPS connections going through a proxy that sends extra data.
6013TEST_F(HttpNetworkTransactionTest, HTTPSViaProxyWithExtraData) {
[email protected]81cdfcd2010-10-16 00:49:006014 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]0877e3d2009-10-17 22:29:576015
6016 HttpRequestInfo request;
6017 request.method = "GET";
6018 request.url = GURL("https://www.google.com/");
6019 request.load_flags = 0;
6020
6021 MockRead proxy_reads[] = {
6022 MockRead("HTTP/1.0 200 Connected\r\n\r\nExtra data"),
6023 MockRead(false, OK)
6024 };
6025
[email protected]31a2bfe2010-02-09 08:03:396026 StaticSocketDataProvider data(proxy_reads, arraysize(proxy_reads), NULL, 0);
[email protected]5ecc992a42009-11-11 01:41:596027 SSLSocketDataProvider ssl(true, OK);
[email protected]0877e3d2009-10-17 22:29:576028
[email protected]5ecc992a42009-11-11 01:41:596029 session_deps.socket_factory.AddSocketDataProvider(&data);
6030 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]0877e3d2009-10-17 22:29:576031
6032 TestCompletionCallback callback;
6033
6034 session_deps.socket_factory.ResetNextMockIndexes();
6035
6036 scoped_ptr<HttpTransaction> trans(
6037 new HttpNetworkTransaction(CreateSession(&session_deps)));
6038
[email protected]5a1d7ca2010-04-28 20:12:276039 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]0877e3d2009-10-17 22:29:576040 EXPECT_EQ(ERR_IO_PENDING, rv);
6041
6042 rv = callback.WaitForResult();
6043 EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, rv);
6044}
6045
[email protected]e22e1362009-11-23 21:31:126046TEST_F(HttpNetworkTransactionTest, LargeContentLengthThenClose) {
[email protected]9492e4a2010-02-24 00:58:466047 HttpRequestInfo request;
6048 request.method = "GET";
6049 request.url = GURL("http://www.google.com/");
6050 request.load_flags = 0;
6051
[email protected]cb9bf6ca2011-01-28 13:15:276052 SessionDependencies session_deps;
6053 scoped_ptr<HttpTransaction> trans(
6054 new HttpNetworkTransaction(CreateSession(&session_deps)));
6055
[email protected]e22e1362009-11-23 21:31:126056 MockRead data_reads[] = {
6057 MockRead("HTTP/1.0 200 OK\r\nContent-Length:6719476739\r\n\r\n"),
6058 MockRead(false, OK),
6059 };
[email protected]9492e4a2010-02-24 00:58:466060
6061 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6062 session_deps.socket_factory.AddSocketDataProvider(&data);
6063
6064 TestCompletionCallback callback;
6065
[email protected]5a1d7ca2010-04-28 20:12:276066 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]9492e4a2010-02-24 00:58:466067 EXPECT_EQ(ERR_IO_PENDING, rv);
6068
6069 EXPECT_EQ(OK, callback.WaitForResult());
6070
6071 const HttpResponseInfo* response = trans->GetResponseInfo();
6072 EXPECT_TRUE(response != NULL);
6073
6074 EXPECT_TRUE(response->headers != NULL);
6075 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6076
6077 std::string response_data;
6078 rv = ReadTransaction(trans.get(), &response_data);
6079 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
[email protected]e22e1362009-11-23 21:31:126080}
6081
[email protected]95d88ffe2010-02-04 21:25:336082TEST_F(HttpNetworkTransactionTest, UploadFileSmallerThanLength) {
[email protected]95d88ffe2010-02-04 21:25:336083 HttpRequestInfo request;
6084 request.method = "POST";
6085 request.url = GURL("http://www.google.com/upload");
6086 request.upload_data = new UploadData;
6087 request.load_flags = 0;
6088
[email protected]cb9bf6ca2011-01-28 13:15:276089 SessionDependencies session_deps;
6090 scoped_ptr<HttpTransaction> trans(
6091 new HttpNetworkTransaction(CreateSession(&session_deps)));
6092
[email protected]95d88ffe2010-02-04 21:25:336093 FilePath temp_file_path;
6094 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file_path));
6095 const uint64 kFakeSize = 100000; // file is actually blank
6096
6097 std::vector<UploadData::Element> elements;
6098 UploadData::Element element;
6099 element.SetToFilePath(temp_file_path);
6100 element.SetContentLength(kFakeSize);
6101 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536102 request.upload_data->SetElements(elements);
[email protected]95d88ffe2010-02-04 21:25:336103 EXPECT_EQ(kFakeSize, request.upload_data->GetContentLength());
6104
6105 MockRead data_reads[] = {
6106 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6107 MockRead("hello world"),
6108 MockRead(false, OK),
6109 };
[email protected]31a2bfe2010-02-09 08:03:396110 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
[email protected]95d88ffe2010-02-04 21:25:336111 session_deps.socket_factory.AddSocketDataProvider(&data);
6112
6113 TestCompletionCallback callback;
6114
[email protected]5a1d7ca2010-04-28 20:12:276115 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]95d88ffe2010-02-04 21:25:336116 EXPECT_EQ(ERR_IO_PENDING, rv);
6117
6118 rv = callback.WaitForResult();
6119 EXPECT_EQ(OK, rv);
6120
6121 const HttpResponseInfo* response = trans->GetResponseInfo();
6122 EXPECT_TRUE(response != NULL);
6123
6124 EXPECT_TRUE(response->headers != NULL);
6125 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6126
6127 std::string response_data;
6128 rv = ReadTransaction(trans.get(), &response_data);
6129 EXPECT_EQ(OK, rv);
6130 EXPECT_EQ("hello world", response_data);
6131
6132 file_util::Delete(temp_file_path, false);
6133}
6134
[email protected]6624b4622010-03-29 19:58:366135TEST_F(HttpNetworkTransactionTest, UploadUnreadableFile) {
[email protected]cb9bf6ca2011-01-28 13:15:276136 HttpRequestInfo request;
6137 request.method = "POST";
6138 request.url = GURL("http://www.google.com/upload");
6139 request.upload_data = new UploadData;
6140 request.load_flags = 0;
6141
[email protected]6624b4622010-03-29 19:58:366142 // If we try to upload an unreadable file, the network stack should report
6143 // the file size as zero and upload zero bytes for that file.
6144 SessionDependencies session_deps;
6145 scoped_ptr<HttpTransaction> trans(
6146 new HttpNetworkTransaction(CreateSession(&session_deps)));
6147
6148 FilePath temp_file;
6149 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6150 std::string temp_file_content("Unreadable file.");
6151 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_content.c_str(),
6152 temp_file_content.length()));
6153 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6154
[email protected]6624b4622010-03-29 19:58:366155 std::vector<UploadData::Element> elements;
6156 UploadData::Element element;
6157 element.SetToFilePath(temp_file);
6158 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536159 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366160
6161 MockRead data_reads[] = {
6162 MockRead("HTTP/1.0 200 OK\r\n\r\n"),
6163 MockRead(false, OK),
6164 };
6165 MockWrite data_writes[] = {
6166 MockWrite("POST /upload HTTP/1.1\r\n"
6167 "Host: www.google.com\r\n"
6168 "Connection: keep-alive\r\n"
6169 "Content-Length: 0\r\n\r\n"),
6170 MockWrite(false, OK),
6171 };
6172 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6173 arraysize(data_writes));
6174 session_deps.socket_factory.AddSocketDataProvider(&data);
6175
6176 TestCompletionCallback callback;
6177
[email protected]5a1d7ca2010-04-28 20:12:276178 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366179 EXPECT_EQ(ERR_IO_PENDING, rv);
6180
6181 rv = callback.WaitForResult();
6182 EXPECT_EQ(OK, rv);
6183
6184 const HttpResponseInfo* response = trans->GetResponseInfo();
6185 EXPECT_TRUE(response != NULL);
6186 EXPECT_TRUE(response->headers != NULL);
6187 EXPECT_EQ("HTTP/1.0 200 OK", response->headers->GetStatusLine());
6188
6189 file_util::Delete(temp_file, false);
6190}
6191
6192TEST_F(HttpNetworkTransactionTest, UnreadableUploadFileAfterAuthRestart) {
[email protected]cb9bf6ca2011-01-28 13:15:276193 HttpRequestInfo request;
6194 request.method = "POST";
6195 request.url = GURL("http://www.google.com/upload");
6196 request.upload_data = new UploadData;
6197 request.load_flags = 0;
6198
[email protected]6624b4622010-03-29 19:58:366199 SessionDependencies session_deps;
6200 scoped_ptr<HttpTransaction> trans(
6201 new HttpNetworkTransaction(CreateSession(&session_deps)));
6202
6203 FilePath temp_file;
6204 ASSERT_TRUE(file_util::CreateTemporaryFile(&temp_file));
6205 std::string temp_file_contents("Unreadable file.");
6206 std::string unreadable_contents(temp_file_contents.length(), '\0');
6207 ASSERT_TRUE(file_util::WriteFile(temp_file, temp_file_contents.c_str(),
6208 temp_file_contents.length()));
6209
[email protected]6624b4622010-03-29 19:58:366210 std::vector<UploadData::Element> elements;
6211 UploadData::Element element;
6212 element.SetToFilePath(temp_file);
6213 elements.push_back(element);
[email protected]9349cfb2010-08-31 18:00:536214 request.upload_data->SetElements(elements);
[email protected]6624b4622010-03-29 19:58:366215
6216 MockRead data_reads[] = {
6217 MockRead("HTTP/1.1 401 Unauthorized\r\n"),
6218 MockRead("WWW-Authenticate: Basic realm=\"MyRealm1\"\r\n"),
6219 MockRead("Content-Length: 0\r\n\r\n"), // No response body.
6220
6221 MockRead("HTTP/1.1 200 OK\r\n"),
6222 MockRead("Content-Length: 0\r\n\r\n"),
6223 MockRead(false, OK),
6224 };
6225 MockWrite data_writes[] = {
6226 MockWrite("POST /upload HTTP/1.1\r\n"
6227 "Host: www.google.com\r\n"
6228 "Connection: keep-alive\r\n"
6229 "Content-Length: 16\r\n\r\n"),
6230 MockWrite(false, temp_file_contents.c_str()),
6231
6232 MockWrite("POST /upload HTTP/1.1\r\n"
6233 "Host: www.google.com\r\n"
6234 "Connection: keep-alive\r\n"
6235 "Content-Length: 16\r\n"
6236 "Authorization: Basic Zm9vOmJhcg==\r\n\r\n"),
6237 MockWrite(false, unreadable_contents.c_str(), temp_file_contents.length()),
6238 MockWrite(false, OK),
6239 };
6240 StaticSocketDataProvider data(data_reads, arraysize(data_reads), data_writes,
6241 arraysize(data_writes));
6242 session_deps.socket_factory.AddSocketDataProvider(&data);
6243
6244 TestCompletionCallback callback1;
6245
[email protected]5a1d7ca2010-04-28 20:12:276246 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]6624b4622010-03-29 19:58:366247 EXPECT_EQ(ERR_IO_PENDING, rv);
6248
6249 rv = callback1.WaitForResult();
6250 EXPECT_EQ(OK, rv);
6251
6252 const HttpResponseInfo* response = trans->GetResponseInfo();
6253 EXPECT_TRUE(response != NULL);
6254 EXPECT_TRUE(response->headers != NULL);
6255 EXPECT_EQ("HTTP/1.1 401 Unauthorized", response->headers->GetStatusLine());
6256
6257 // The password prompt info should have been set in response->auth_challenge.
6258 EXPECT_TRUE(response->auth_challenge.get() != NULL);
6259 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6260 EXPECT_EQ(L"MyRealm1", response->auth_challenge->realm);
6261 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6262
6263 // Now make the file unreadable and try again.
6264 ASSERT_TRUE(file_util::MakeFileUnreadable(temp_file));
6265
6266 TestCompletionCallback callback2;
6267
[email protected]13c8a092010-07-29 06:15:446268 rv = trans->RestartWithAuth(kFoo, kBar, &callback2);
[email protected]6624b4622010-03-29 19:58:366269 EXPECT_EQ(ERR_IO_PENDING, rv);
6270
6271 rv = callback2.WaitForResult();
6272 EXPECT_EQ(OK, rv);
6273
6274 response = trans->GetResponseInfo();
6275 EXPECT_TRUE(response != NULL);
6276 EXPECT_TRUE(response->headers != NULL);
6277 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6278 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6279
6280 file_util::Delete(temp_file, false);
6281}
6282
[email protected]aeefc9e82010-02-19 16:18:276283// Tests that changes to Auth realms are treated like auth rejections.
6284TEST_F(HttpNetworkTransactionTest, ChangeAuthRealms) {
6285 SessionDependencies session_deps;
[email protected]aeefc9e82010-02-19 16:18:276286
6287 HttpRequestInfo request;
6288 request.method = "GET";
6289 request.url = GURL("http://www.google.com/");
6290 request.load_flags = 0;
6291
6292 // First transaction will request a resource and receive a Basic challenge
6293 // with realm="first_realm".
6294 MockWrite data_writes1[] = {
6295 MockWrite("GET / HTTP/1.1\r\n"
6296 "Host: www.google.com\r\n"
6297 "Connection: keep-alive\r\n"
6298 "\r\n"),
6299 };
6300 MockRead data_reads1[] = {
6301 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6302 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6303 "\r\n"),
6304 };
6305
6306 // After calling trans->RestartWithAuth(), provide an Authentication header
6307 // for first_realm. The server will reject and provide a challenge with
6308 // second_realm.
6309 MockWrite data_writes2[] = {
6310 MockWrite("GET / HTTP/1.1\r\n"
6311 "Host: www.google.com\r\n"
6312 "Connection: keep-alive\r\n"
6313 "Authorization: Basic Zmlyc3Q6YmF6\r\n"
6314 "\r\n"),
6315 };
6316 MockRead data_reads2[] = {
6317 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6318 "WWW-Authenticate: Basic realm=\"second_realm\"\r\n"
6319 "\r\n"),
6320 };
6321
6322 // This again fails, and goes back to first_realm. Make sure that the
6323 // entry is removed from cache.
6324 MockWrite data_writes3[] = {
6325 MockWrite("GET / HTTP/1.1\r\n"
6326 "Host: www.google.com\r\n"
6327 "Connection: keep-alive\r\n"
6328 "Authorization: Basic c2Vjb25kOmZvdQ==\r\n"
6329 "\r\n"),
6330 };
6331 MockRead data_reads3[] = {
6332 MockRead("HTTP/1.1 401 Unauthorized\r\n"
6333 "WWW-Authenticate: Basic realm=\"first_realm\"\r\n"
6334 "\r\n"),
6335 };
6336
6337 // Try one last time (with the correct password) and get the resource.
6338 MockWrite data_writes4[] = {
6339 MockWrite("GET / HTTP/1.1\r\n"
6340 "Host: www.google.com\r\n"
6341 "Connection: keep-alive\r\n"
6342 "Authorization: Basic Zmlyc3Q6YmFy\r\n"
6343 "\r\n"),
6344 };
6345 MockRead data_reads4[] = {
6346 MockRead("HTTP/1.1 200 OK\r\n"
6347 "Content-Type: text/html; charset=iso-8859-1\r\n"
[email protected]0b0bf032010-09-21 18:08:506348 "Content-Length: 5\r\n"
6349 "\r\n"
6350 "hello"),
[email protected]aeefc9e82010-02-19 16:18:276351 };
6352
6353 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
6354 data_writes1, arraysize(data_writes1));
6355 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2),
6356 data_writes2, arraysize(data_writes2));
6357 StaticSocketDataProvider data3(data_reads3, arraysize(data_reads3),
6358 data_writes3, arraysize(data_writes3));
6359 StaticSocketDataProvider data4(data_reads4, arraysize(data_reads4),
6360 data_writes4, arraysize(data_writes4));
6361 session_deps.socket_factory.AddSocketDataProvider(&data1);
6362 session_deps.socket_factory.AddSocketDataProvider(&data2);
6363 session_deps.socket_factory.AddSocketDataProvider(&data3);
6364 session_deps.socket_factory.AddSocketDataProvider(&data4);
6365
6366 TestCompletionCallback callback1;
6367
[email protected]0b0bf032010-09-21 18:08:506368 scoped_ptr<HttpTransaction> trans(
6369 new HttpNetworkTransaction(CreateSession(&session_deps)));
6370
[email protected]aeefc9e82010-02-19 16:18:276371 // Issue the first request with Authorize headers. There should be a
6372 // password prompt for first_realm waiting to be filled in after the
6373 // transaction completes.
[email protected]5a1d7ca2010-04-28 20:12:276374 int rv = trans->Start(&request, &callback1, BoundNetLog());
[email protected]aeefc9e82010-02-19 16:18:276375 EXPECT_EQ(ERR_IO_PENDING, rv);
6376 rv = callback1.WaitForResult();
6377 EXPECT_EQ(OK, rv);
6378 const HttpResponseInfo* response = trans->GetResponseInfo();
6379 ASSERT_FALSE(response == NULL);
6380 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6381 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6382 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6383 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6384
6385 // Issue the second request with an incorrect password. There should be a
6386 // password prompt for second_realm waiting to be filled in after the
6387 // transaction completes.
6388 TestCompletionCallback callback2;
[email protected]13c8a092010-07-29 06:15:446389 rv = trans->RestartWithAuth(kFirst, kBaz, &callback2);
[email protected]aeefc9e82010-02-19 16:18:276390 EXPECT_EQ(ERR_IO_PENDING, rv);
6391 rv = callback2.WaitForResult();
6392 EXPECT_EQ(OK, rv);
6393 response = trans->GetResponseInfo();
6394 ASSERT_FALSE(response == NULL);
6395 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6396 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6397 EXPECT_EQ(L"second_realm", response->auth_challenge->realm);
6398 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6399
6400 // Issue the third request with another incorrect password. There should be
6401 // a password prompt for first_realm waiting to be filled in. If the password
6402 // prompt is not present, it indicates that the HttpAuthCacheEntry for
6403 // first_realm was not correctly removed.
6404 TestCompletionCallback callback3;
[email protected]13c8a092010-07-29 06:15:446405 rv = trans->RestartWithAuth(kSecond, kFou, &callback3);
[email protected]aeefc9e82010-02-19 16:18:276406 EXPECT_EQ(ERR_IO_PENDING, rv);
6407 rv = callback3.WaitForResult();
6408 EXPECT_EQ(OK, rv);
6409 response = trans->GetResponseInfo();
6410 ASSERT_FALSE(response == NULL);
6411 ASSERT_FALSE(response->auth_challenge.get() == NULL);
6412 EXPECT_EQ(L"www.google.com:80", response->auth_challenge->host_and_port);
6413 EXPECT_EQ(L"first_realm", response->auth_challenge->realm);
6414 EXPECT_EQ(L"basic", response->auth_challenge->scheme);
6415
6416 // Issue the fourth request with the correct password and username.
6417 TestCompletionCallback callback4;
[email protected]13c8a092010-07-29 06:15:446418 rv = trans->RestartWithAuth(kFirst, kBar, &callback4);
[email protected]aeefc9e82010-02-19 16:18:276419 EXPECT_EQ(ERR_IO_PENDING, rv);
6420 rv = callback4.WaitForResult();
6421 EXPECT_EQ(OK, rv);
6422 response = trans->GetResponseInfo();
6423 ASSERT_FALSE(response == NULL);
6424 EXPECT_TRUE(response->auth_challenge.get() == NULL);
6425}
6426
[email protected]564b4912010-03-09 16:30:426427TEST_F(HttpNetworkTransactionTest, HonorAlternateProtocolHeader) {
[email protected]8e6441ca2010-08-19 05:56:386428 HttpStreamFactory::set_next_protos("needs_to_be_set_for_this_test");
6429 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]a2cb8122010-03-10 17:22:426430
[email protected]564b4912010-03-09 16:30:426431 SessionDependencies session_deps;
6432
6433 MockRead data_reads[] = {
6434 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356435 MockRead(kAlternateProtocolHttpHeader),
[email protected]564b4912010-03-09 16:30:426436 MockRead("hello world"),
6437 MockRead(false, OK),
6438 };
6439
6440 HttpRequestInfo request;
6441 request.method = "GET";
6442 request.url = GURL("http://www.google.com/");
6443 request.load_flags = 0;
6444
6445 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
6446
6447 session_deps.socket_factory.AddSocketDataProvider(&data);
6448
6449 TestCompletionCallback callback;
6450
6451 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6452 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6453
[email protected]5a1d7ca2010-04-28 20:12:276454 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426455 EXPECT_EQ(ERR_IO_PENDING, rv);
[email protected]9e743cd2010-03-16 07:03:536456
[email protected]2fbaecf22010-07-22 22:20:356457 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426458 const HttpAlternateProtocols& alternate_protocols =
6459 session->alternate_protocols();
6460 EXPECT_FALSE(
6461 alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6462
6463 EXPECT_EQ(OK, callback.WaitForResult());
6464
6465 const HttpResponseInfo* response = trans->GetResponseInfo();
6466 ASSERT_TRUE(response != NULL);
6467 ASSERT_TRUE(response->headers != NULL);
6468 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536469 EXPECT_FALSE(response->was_fetched_via_spdy);
6470 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]564b4912010-03-09 16:30:426471
6472 std::string response_data;
6473 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6474 EXPECT_EQ("hello world", response_data);
6475
6476 ASSERT_TRUE(alternate_protocols.HasAlternateProtocolFor(http_host_port_pair));
6477 const HttpAlternateProtocols::PortProtocolPair alternate =
6478 alternate_protocols.GetAlternateProtocolFor(http_host_port_pair);
6479 HttpAlternateProtocols::PortProtocolPair expected_alternate;
6480 expected_alternate.port = 443;
[email protected]dae22c52010-07-30 02:16:356481 expected_alternate.protocol = HttpAlternateProtocols::NPN_SPDY_2;
[email protected]564b4912010-03-09 16:30:426482 EXPECT_TRUE(expected_alternate.Equals(alternate));
[email protected]a2cb8122010-03-10 17:22:426483
[email protected]8e6441ca2010-08-19 05:56:386484 HttpStreamFactory::set_use_alternate_protocols(false);
6485 HttpStreamFactory::set_next_protos("");
[email protected]564b4912010-03-09 16:30:426486}
6487
[email protected]8b95ed62011-03-18 18:12:036488TEST_F(HttpNetworkTransactionTest, MarkBrokenAlternateProtocolAndFallback) {
[email protected]8e6441ca2010-08-19 05:56:386489 HttpStreamFactory::set_use_alternate_protocols(true);
[email protected]564b4912010-03-09 16:30:426490 SessionDependencies session_deps;
6491
6492 HttpRequestInfo request;
6493 request.method = "GET";
6494 request.url = GURL("http://www.google.com/");
6495 request.load_flags = 0;
6496
6497 MockConnect mock_connect(true, ERR_CONNECTION_REFUSED);
6498 StaticSocketDataProvider first_data;
6499 first_data.set_connect_data(mock_connect);
6500 session_deps.socket_factory.AddSocketDataProvider(&first_data);
6501
6502 MockRead data_reads[] = {
6503 MockRead("HTTP/1.1 200 OK\r\n\r\n"),
6504 MockRead("hello world"),
6505 MockRead(true, OK),
6506 };
6507 StaticSocketDataProvider second_data(
6508 data_reads, arraysize(data_reads), NULL, 0);
6509 session_deps.socket_factory.AddSocketDataProvider(&second_data);
6510
[email protected]564b4912010-03-09 16:30:426511 TestCompletionCallback callback;
6512
6513 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6514
[email protected]2fbaecf22010-07-22 22:20:356515 HostPortPair http_host_port_pair("www.google.com", 80);
[email protected]564b4912010-03-09 16:30:426516 HttpAlternateProtocols* alternate_protocols =
6517 session->mutable_alternate_protocols();
6518 alternate_protocols->SetAlternateProtocolFor(
6519 http_host_port_pair, 1234 /* port is ignored by MockConnect anyway */,
[email protected]dae22c52010-07-30 02:16:356520 HttpAlternateProtocols::NPN_SPDY_2);
[email protected]564b4912010-03-09 16:30:426521
6522 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
6523
[email protected]5a1d7ca2010-04-28 20:12:276524 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]564b4912010-03-09 16:30:426525 EXPECT_EQ(ERR_IO_PENDING, rv);
6526 EXPECT_EQ(OK, callback.WaitForResult());
6527
6528 const HttpResponseInfo* response = trans->GetResponseInfo();
6529 ASSERT_TRUE(response != NULL);
6530 ASSERT_TRUE(response->headers != NULL);
6531 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6532
6533 std::string response_data;
6534 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6535 EXPECT_EQ("hello world", response_data);
6536
6537 ASSERT_TRUE(
6538 alternate_protocols->HasAlternateProtocolFor(http_host_port_pair));
6539 const HttpAlternateProtocols::PortProtocolPair alternate =
6540 alternate_protocols->GetAlternateProtocolFor(http_host_port_pair);
6541 EXPECT_EQ(HttpAlternateProtocols::BROKEN, alternate.protocol);
[email protected]8e6441ca2010-08-19 05:56:386542 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:426543}
6544
[email protected]2ff8b312010-04-26 22:20:546545TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386546 HttpStreamFactory::set_use_alternate_protocols(true);
6547 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546548 SessionDependencies session_deps;
6549
6550 HttpRequestInfo request;
6551 request.method = "GET";
6552 request.url = GURL("http://www.google.com/");
6553 request.load_flags = 0;
6554
6555 MockRead data_reads[] = {
6556 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356557 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546558 MockRead("hello world"),
6559 MockRead(true, OK),
6560 };
6561
6562 StaticSocketDataProvider first_transaction(
6563 data_reads, arraysize(data_reads), NULL, 0);
6564 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6565
6566 SSLSocketDataProvider ssl(true, OK);
6567 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356568 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536569 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:546570 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6571
[email protected]2bd93022010-07-17 00:58:446572 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:136573 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:546574
[email protected]2bd93022010-07-17 00:58:446575 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6576 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:546577 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:136578 CreateMockRead(*resp),
6579 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:546580 MockRead(true, 0, 0),
6581 };
6582
6583 scoped_refptr<DelayedSocketData> spdy_data(
6584 new DelayedSocketData(
6585 1, // wait for one write to finish before reading.
6586 spdy_reads, arraysize(spdy_reads),
6587 spdy_writes, arraysize(spdy_writes)));
6588 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6589
[email protected]2d6728692011-03-12 01:39:556590 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6591 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6592 NULL, 0, NULL, 0);
6593 hanging_non_alternate_protocol_socket.set_connect_data(
6594 never_finishing_connect);
6595 session_deps.socket_factory.AddSocketDataProvider(
6596 &hanging_non_alternate_protocol_socket);
6597
[email protected]2ff8b312010-04-26 22:20:546598 TestCompletionCallback callback;
6599
6600 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6601 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6602
[email protected]5a1d7ca2010-04-28 20:12:276603 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546604 EXPECT_EQ(ERR_IO_PENDING, rv);
6605 EXPECT_EQ(OK, callback.WaitForResult());
6606
6607 const HttpResponseInfo* response = trans->GetResponseInfo();
6608 ASSERT_TRUE(response != NULL);
6609 ASSERT_TRUE(response->headers != NULL);
6610 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6611
6612 std::string response_data;
6613 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6614 EXPECT_EQ("hello world", response_data);
6615
6616 trans.reset(new HttpNetworkTransaction(session));
6617
[email protected]5a1d7ca2010-04-28 20:12:276618 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:546619 EXPECT_EQ(ERR_IO_PENDING, rv);
6620 EXPECT_EQ(OK, callback.WaitForResult());
6621
6622 response = trans->GetResponseInfo();
6623 ASSERT_TRUE(response != NULL);
6624 ASSERT_TRUE(response->headers != NULL);
6625 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536626 EXPECT_TRUE(response->was_fetched_via_spdy);
6627 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:546628
6629 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6630 EXPECT_EQ("hello!", response_data);
6631
[email protected]8e6441ca2010-08-19 05:56:386632 HttpStreamFactory::set_next_protos("");
6633 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]2ff8b312010-04-26 22:20:546634}
6635
[email protected]2d6728692011-03-12 01:39:556636TEST_F(HttpNetworkTransactionTest, AlternateProtocolWithSpdyLateBinding) {
6637 HttpStreamFactory::set_use_alternate_protocols(true);
6638 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6639 SessionDependencies session_deps;
6640
6641 HttpRequestInfo request;
6642 request.method = "GET";
6643 request.url = GURL("http://www.google.com/");
6644 request.load_flags = 0;
6645
6646 MockRead data_reads[] = {
6647 MockRead("HTTP/1.1 200 OK\r\n"),
6648 MockRead(kAlternateProtocolHttpHeader),
6649 MockRead("hello world"),
6650 MockRead(true, OK),
6651 };
6652
6653 StaticSocketDataProvider first_transaction(
6654 data_reads, arraysize(data_reads), NULL, 0);
6655 // Socket 1 is the HTTP transaction with the Alternate-Protocol header.
6656 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6657
6658 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6659 StaticSocketDataProvider hanging_socket(
6660 NULL, 0, NULL, 0);
6661 hanging_socket.set_connect_data(never_finishing_connect);
6662 // Socket 2 and 3 are the hanging Alternate-Protocol and
6663 // non-Alternate-Protocol jobs from the 2nd transaction.
6664 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6665 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6666
6667 SSLSocketDataProvider ssl(true, OK);
6668 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6669 ssl.next_proto = "spdy/2";
6670 ssl.was_npn_negotiated = true;
6671 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6672
6673 scoped_ptr<spdy::SpdyFrame> req1(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
6674 scoped_ptr<spdy::SpdyFrame> req2(ConstructSpdyGet(NULL, 0, false, 3, LOWEST));
6675 MockWrite spdy_writes[] = {
6676 CreateMockWrite(*req1),
6677 CreateMockWrite(*req2),
6678 };
6679 scoped_ptr<spdy::SpdyFrame> resp1(ConstructSpdyGetSynReply(NULL, 0, 1));
6680 scoped_ptr<spdy::SpdyFrame> data1(ConstructSpdyBodyFrame(1, true));
6681 scoped_ptr<spdy::SpdyFrame> resp2(ConstructSpdyGetSynReply(NULL, 0, 3));
6682 scoped_ptr<spdy::SpdyFrame> data2(ConstructSpdyBodyFrame(3, true));
6683 MockRead spdy_reads[] = {
6684 CreateMockRead(*resp1),
6685 CreateMockRead(*data1),
6686 CreateMockRead(*resp2),
6687 CreateMockRead(*data2),
6688 MockRead(true, 0, 0),
6689 };
6690
6691 scoped_refptr<DelayedSocketData> spdy_data(
6692 new DelayedSocketData(
6693 2, // wait for writes to finish before reading.
6694 spdy_reads, arraysize(spdy_reads),
6695 spdy_writes, arraysize(spdy_writes)));
6696 // Socket 4 is the successful Alternate-Protocol for transaction 3.
6697 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6698
6699 // Socket 5 is the unsuccessful non-Alternate-Protocol for transaction 3.
6700 session_deps.socket_factory.AddSocketDataProvider(&hanging_socket);
6701
6702 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6703 TestCompletionCallback callback1;
6704 HttpNetworkTransaction trans1(session);
6705
6706 int rv = trans1.Start(&request, &callback1, BoundNetLog());
6707 EXPECT_EQ(ERR_IO_PENDING, rv);
6708 EXPECT_EQ(OK, callback1.WaitForResult());
6709
6710 const HttpResponseInfo* response = trans1.GetResponseInfo();
6711 ASSERT_TRUE(response != NULL);
6712 ASSERT_TRUE(response->headers != NULL);
6713 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6714
6715 std::string response_data;
6716 ASSERT_EQ(OK, ReadTransaction(&trans1, &response_data));
6717 EXPECT_EQ("hello world", response_data);
6718
6719 TestCompletionCallback callback2;
6720 HttpNetworkTransaction trans2(session);
6721 rv = trans2.Start(&request, &callback2, BoundNetLog());
6722 EXPECT_EQ(ERR_IO_PENDING, rv);
6723
6724 TestCompletionCallback callback3;
6725 HttpNetworkTransaction trans3(session);
6726 rv = trans3.Start(&request, &callback3, BoundNetLog());
6727 EXPECT_EQ(ERR_IO_PENDING, rv);
6728
6729 EXPECT_EQ(OK, callback2.WaitForResult());
6730 EXPECT_EQ(OK, callback3.WaitForResult());
6731
6732 response = trans2.GetResponseInfo();
6733 ASSERT_TRUE(response != NULL);
6734 ASSERT_TRUE(response->headers != NULL);
6735 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6736 EXPECT_TRUE(response->was_fetched_via_spdy);
6737 EXPECT_TRUE(response->was_npn_negotiated);
6738 ASSERT_EQ(OK, ReadTransaction(&trans2, &response_data));
6739 EXPECT_EQ("hello!", response_data);
6740
6741 response = trans3.GetResponseInfo();
6742 ASSERT_TRUE(response != NULL);
6743 ASSERT_TRUE(response->headers != NULL);
6744 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6745 EXPECT_TRUE(response->was_fetched_via_spdy);
6746 EXPECT_TRUE(response->was_npn_negotiated);
6747 ASSERT_EQ(OK, ReadTransaction(&trans3, &response_data));
6748 EXPECT_EQ("hello!", response_data);
6749
6750 HttpStreamFactory::set_next_protos("");
6751 HttpStreamFactory::set_use_alternate_protocols(false);
6752}
6753
6754TEST_F(HttpNetworkTransactionTest, StallAlternateProtocolForNpnSpdy) {
6755 HttpStreamFactory::set_use_alternate_protocols(true);
6756 HttpStreamFactory::set_next_protos(kExpectedNPNString);
6757 SessionDependencies session_deps;
6758
6759 HttpRequestInfo request;
6760 request.method = "GET";
6761 request.url = GURL("http://www.google.com/");
6762 request.load_flags = 0;
6763
6764 MockRead data_reads[] = {
6765 MockRead("HTTP/1.1 200 OK\r\n"),
6766 MockRead(kAlternateProtocolHttpHeader),
6767 MockRead("hello world"),
6768 MockRead(true, OK),
6769 };
6770
6771 StaticSocketDataProvider first_transaction(
6772 data_reads, arraysize(data_reads), NULL, 0);
6773 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6774
6775 SSLSocketDataProvider ssl(true, OK);
6776 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
6777 ssl.next_proto = "spdy/2";
6778 ssl.was_npn_negotiated = true;
6779 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6780
6781 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6782 StaticSocketDataProvider hanging_alternate_protocol_socket(
6783 NULL, 0, NULL, 0);
6784 hanging_alternate_protocol_socket.set_connect_data(
6785 never_finishing_connect);
6786 session_deps.socket_factory.AddSocketDataProvider(
6787 &hanging_alternate_protocol_socket);
6788
6789 // 2nd request is just a copy of the first one, over HTTP again.
6790 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6791
6792 TestCompletionCallback callback;
6793
6794 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6795 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6796
6797 int rv = trans->Start(&request, &callback, BoundNetLog());
6798 EXPECT_EQ(ERR_IO_PENDING, rv);
6799 EXPECT_EQ(OK, callback.WaitForResult());
6800
6801 const HttpResponseInfo* response = trans->GetResponseInfo();
6802 ASSERT_TRUE(response != NULL);
6803 ASSERT_TRUE(response->headers != NULL);
6804 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6805
6806 std::string response_data;
6807 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6808 EXPECT_EQ("hello world", response_data);
6809
6810 trans.reset(new HttpNetworkTransaction(session));
6811
6812 rv = trans->Start(&request, &callback, BoundNetLog());
6813 EXPECT_EQ(ERR_IO_PENDING, rv);
6814 EXPECT_EQ(OK, callback.WaitForResult());
6815
6816 response = trans->GetResponseInfo();
6817 ASSERT_TRUE(response != NULL);
6818 ASSERT_TRUE(response->headers != NULL);
6819 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
6820 EXPECT_FALSE(response->was_fetched_via_spdy);
6821 EXPECT_FALSE(response->was_npn_negotiated);
6822
6823 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6824 EXPECT_EQ("hello world", response_data);
6825
6826 HttpStreamFactory::set_next_protos("");
6827 HttpStreamFactory::set_use_alternate_protocols(false);
6828}
6829
[email protected]631f1322010-04-30 17:59:116830class CapturingProxyResolver : public ProxyResolver {
6831 public:
6832 CapturingProxyResolver() : ProxyResolver(false /* expects_pac_bytes */) {}
6833 virtual ~CapturingProxyResolver() {}
6834
6835 virtual int GetProxyForURL(const GURL& url,
6836 ProxyInfo* results,
6837 CompletionCallback* callback,
6838 RequestHandle* request,
6839 const BoundNetLog& net_log) {
[email protected]fae7669f2010-08-02 21:49:406840 ProxyServer proxy_server(ProxyServer::SCHEME_HTTP,
6841 HostPortPair("myproxy", 80));
[email protected]d911f1b2010-05-05 22:39:426842 results->UseProxyServer(proxy_server);
[email protected]631f1322010-04-30 17:59:116843 resolved_.push_back(url);
[email protected]d911f1b2010-05-05 22:39:426844 return OK;
[email protected]631f1322010-04-30 17:59:116845 }
6846
6847 virtual void CancelRequest(RequestHandle request) {
6848 NOTREACHED();
6849 }
6850
[email protected]1e605472010-12-16 21:41:406851 virtual void CancelSetPacScript() {
6852 NOTREACHED();
6853 }
6854
[email protected]24476402010-07-20 20:55:176855 virtual int SetPacScript(const scoped_refptr<ProxyResolverScriptData>&,
[email protected]631f1322010-04-30 17:59:116856 CompletionCallback* /*callback*/) {
[email protected]d911f1b2010-05-05 22:39:426857 return OK;
[email protected]631f1322010-04-30 17:59:116858 }
6859
[email protected]24476402010-07-20 20:55:176860 const std::vector<GURL>& resolved() const { return resolved_; }
6861
6862 private:
[email protected]631f1322010-04-30 17:59:116863 std::vector<GURL> resolved_;
6864
6865 DISALLOW_COPY_AND_ASSIGN(CapturingProxyResolver);
6866};
6867
[email protected]631f1322010-04-30 17:59:116868TEST_F(HttpNetworkTransactionTest, UseAlternateProtocolForTunneledNpnSpdy) {
[email protected]8e6441ca2010-08-19 05:56:386869 HttpStreamFactory::set_use_alternate_protocols(true);
6870 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]631f1322010-04-30 17:59:116871
6872 ProxyConfig proxy_config;
[email protected]d911f1b2010-05-05 22:39:426873 proxy_config.set_auto_detect(true);
6874 proxy_config.set_pac_url(GURL("http://fooproxyurl"));
[email protected]2227c692010-05-04 15:36:116875
[email protected]631f1322010-04-30 17:59:116876 CapturingProxyResolver* capturing_proxy_resolver =
6877 new CapturingProxyResolver();
[email protected]66761b952010-06-25 21:30:386878 SessionDependencies session_deps(new ProxyService(
6879 new ProxyConfigServiceFixed(proxy_config), capturing_proxy_resolver,
6880 NULL));
[email protected]631f1322010-04-30 17:59:116881
6882 HttpRequestInfo request;
6883 request.method = "GET";
6884 request.url = GURL("http://www.google.com/");
6885 request.load_flags = 0;
6886
6887 MockRead data_reads[] = {
6888 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356889 MockRead(kAlternateProtocolHttpHeader),
[email protected]631f1322010-04-30 17:59:116890 MockRead("hello world"),
6891 MockRead(true, OK),
6892 };
6893
6894 StaticSocketDataProvider first_transaction(
6895 data_reads, arraysize(data_reads), NULL, 0);
6896 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
6897
6898 SSLSocketDataProvider ssl(true, OK);
6899 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:356900 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:536901 ssl.was_npn_negotiated = true;
[email protected]631f1322010-04-30 17:59:116902 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
6903
[email protected]2bd93022010-07-17 00:58:446904 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]631f1322010-04-30 17:59:116905 MockWrite spdy_writes[] = {
6906 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
6907 "Host: www.google.com\r\n"
[email protected]d911f1b2010-05-05 22:39:426908 "Proxy-Connection: keep-alive\r\n\r\n"), // 0
[email protected]e7f75092010-07-01 22:39:136909 CreateMockWrite(*req) // 3
[email protected]631f1322010-04-30 17:59:116910 };
6911
[email protected]d911f1b2010-05-05 22:39:426912 const char kCONNECTResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
6913
[email protected]2bd93022010-07-17 00:58:446914 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
6915 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]631f1322010-04-30 17:59:116916 MockRead spdy_reads[] = {
[email protected]d911f1b2010-05-05 22:39:426917 MockRead(true, kCONNECTResponse, arraysize(kCONNECTResponse) - 1, 1), // 1
[email protected]e7f75092010-07-01 22:39:136918 CreateMockRead(*resp.get(), 4), // 2, 4
6919 CreateMockRead(*data.get(), 4), // 5
[email protected]d911f1b2010-05-05 22:39:426920 MockRead(true, 0, 0, 4), // 6
[email protected]631f1322010-04-30 17:59:116921 };
6922
[email protected]d911f1b2010-05-05 22:39:426923 scoped_refptr<OrderedSocketData> spdy_data(
6924 new OrderedSocketData(
[email protected]631f1322010-04-30 17:59:116925 spdy_reads, arraysize(spdy_reads),
6926 spdy_writes, arraysize(spdy_writes)));
6927 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
6928
[email protected]2d6728692011-03-12 01:39:556929 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
6930 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
6931 NULL, 0, NULL, 0);
6932 hanging_non_alternate_protocol_socket.set_connect_data(
6933 never_finishing_connect);
6934 session_deps.socket_factory.AddSocketDataProvider(
6935 &hanging_non_alternate_protocol_socket);
6936
[email protected]631f1322010-04-30 17:59:116937 TestCompletionCallback callback;
6938
6939 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
6940 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
6941
6942 int rv = trans->Start(&request, &callback, BoundNetLog());
6943 EXPECT_EQ(ERR_IO_PENDING, rv);
6944 EXPECT_EQ(OK, callback.WaitForResult());
6945
6946 const HttpResponseInfo* response = trans->GetResponseInfo();
6947 ASSERT_TRUE(response != NULL);
6948 ASSERT_TRUE(response->headers != NULL);
6949 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536950 EXPECT_FALSE(response->was_fetched_via_spdy);
6951 EXPECT_FALSE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116952
6953 std::string response_data;
6954 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6955 EXPECT_EQ("hello world", response_data);
6956
6957 trans.reset(new HttpNetworkTransaction(session));
6958
6959 rv = trans->Start(&request, &callback, BoundNetLog());
6960 EXPECT_EQ(ERR_IO_PENDING, rv);
6961 EXPECT_EQ(OK, callback.WaitForResult());
6962
6963 response = trans->GetResponseInfo();
6964 ASSERT_TRUE(response != NULL);
6965 ASSERT_TRUE(response->headers != NULL);
6966 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:536967 EXPECT_TRUE(response->was_fetched_via_spdy);
6968 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]631f1322010-04-30 17:59:116969
6970 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
6971 EXPECT_EQ("hello!", response_data);
[email protected]2d6728692011-03-12 01:39:556972 ASSERT_EQ(3u, capturing_proxy_resolver->resolved().size());
[email protected]d911f1b2010-05-05 22:39:426973 EXPECT_EQ("http://www.google.com/",
[email protected]631f1322010-04-30 17:59:116974 capturing_proxy_resolver->resolved()[0].spec());
[email protected]d911f1b2010-05-05 22:39:426975 EXPECT_EQ("https://www.google.com/",
6976 capturing_proxy_resolver->resolved()[1].spec());
[email protected]631f1322010-04-30 17:59:116977
[email protected]8e6441ca2010-08-19 05:56:386978 HttpStreamFactory::set_next_protos("");
6979 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]631f1322010-04-30 17:59:116980}
[email protected]631f1322010-04-30 17:59:116981
[email protected]2ff8b312010-04-26 22:20:546982TEST_F(HttpNetworkTransactionTest,
6983 UseAlternateProtocolForNpnSpdyWithExistingSpdySession) {
[email protected]8e6441ca2010-08-19 05:56:386984 HttpStreamFactory::set_use_alternate_protocols(true);
6985 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]2ff8b312010-04-26 22:20:546986 SessionDependencies session_deps;
6987
6988 HttpRequestInfo request;
6989 request.method = "GET";
6990 request.url = GURL("http://www.google.com/");
6991 request.load_flags = 0;
6992
6993 MockRead data_reads[] = {
6994 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:356995 MockRead(kAlternateProtocolHttpHeader),
[email protected]2ff8b312010-04-26 22:20:546996 MockRead("hello world"),
6997 MockRead(true, OK),
6998 };
6999
7000 StaticSocketDataProvider first_transaction(
7001 data_reads, arraysize(data_reads), NULL, 0);
7002 session_deps.socket_factory.AddSocketDataProvider(&first_transaction);
7003
7004 SSLSocketDataProvider ssl(true, OK);
7005 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357006 ssl.next_proto = "spdy/2";
[email protected]65041fa2010-05-21 06:56:537007 ssl.was_npn_negotiated = true;
[email protected]2ff8b312010-04-26 22:20:547008 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]65041fa2010-05-21 06:56:537009 // Make sure we use ssl for spdy here.
7010 SpdySession::SetSSLMode(true);
[email protected]2ff8b312010-04-26 22:20:547011
[email protected]2bd93022010-07-17 00:58:447012 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137013 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]2ff8b312010-04-26 22:20:547014
[email protected]2bd93022010-07-17 00:58:447015 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7016 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
[email protected]2ff8b312010-04-26 22:20:547017 MockRead spdy_reads[] = {
[email protected]e7f75092010-07-01 22:39:137018 CreateMockRead(*resp),
7019 CreateMockRead(*data),
[email protected]2ff8b312010-04-26 22:20:547020 MockRead(true, 0, 0),
7021 };
7022
7023 scoped_refptr<DelayedSocketData> spdy_data(
7024 new DelayedSocketData(
7025 1, // wait for one write to finish before reading.
7026 spdy_reads, arraysize(spdy_reads),
7027 spdy_writes, arraysize(spdy_writes)));
7028 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7029
7030 TestCompletionCallback callback;
7031
7032 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7033
7034 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7035
[email protected]5a1d7ca2010-04-28 20:12:277036 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547037 EXPECT_EQ(ERR_IO_PENDING, rv);
7038 EXPECT_EQ(OK, callback.WaitForResult());
7039
7040 const HttpResponseInfo* response = trans->GetResponseInfo();
7041 ASSERT_TRUE(response != NULL);
7042 ASSERT_TRUE(response->headers != NULL);
7043 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7044
7045 std::string response_data;
7046 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7047 EXPECT_EQ("hello world", response_data);
7048
7049 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:387050 HostPortPair host_port_pair("www.google.com", 443);
7051 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]2ff8b312010-04-26 22:20:547052 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:317053 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:287054 scoped_refptr<TransportSocketParams> transport_params(
7055 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:387056
7057 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
7058 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:287059 connection->Init(host_port_pair.ToString(),
7060 transport_params,
7061 LOWEST,
7062 &callback,
7063 session->transport_socket_pool(),
[email protected]02b0c342010-09-25 21:09:387064 BoundNetLog()));
7065 EXPECT_EQ(OK, callback.WaitForResult());
7066
7067 SSLConfig ssl_config;
7068 session->ssl_config_service()->GetSSLConfig(&ssl_config);
[email protected]9e1bdd32011-02-03 21:48:347069 scoped_ptr<ClientSocketHandle> ssl_connection(new ClientSocketHandle);
7070 ssl_connection->set_socket(session_deps.socket_factory.CreateSSLClientSocket(
7071 connection.release(), HostPortPair("" , 443), ssl_config,
7072 NULL /* ssl_host_info */, session_deps.cert_verifier.get(), NULL));
7073 EXPECT_EQ(ERR_IO_PENDING, ssl_connection->socket()->Connect(&callback));
[email protected]02b0c342010-09-25 21:09:387074 EXPECT_EQ(OK, callback.WaitForResult());
7075
[email protected]9e1bdd32011-02-03 21:48:347076 EXPECT_EQ(OK, spdy_session->InitializeWithSocket(ssl_connection.release(),
[email protected]02b0c342010-09-25 21:09:387077 true, OK));
7078
[email protected]2ff8b312010-04-26 22:20:547079 trans.reset(new HttpNetworkTransaction(session));
7080
[email protected]5a1d7ca2010-04-28 20:12:277081 rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]2ff8b312010-04-26 22:20:547082 EXPECT_EQ(ERR_IO_PENDING, rv);
7083 EXPECT_EQ(OK, callback.WaitForResult());
7084
7085 response = trans->GetResponseInfo();
7086 ASSERT_TRUE(response != NULL);
7087 ASSERT_TRUE(response->headers != NULL);
7088 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
[email protected]65041fa2010-05-21 06:56:537089 EXPECT_TRUE(response->was_fetched_via_spdy);
7090 EXPECT_TRUE(response->was_npn_negotiated);
[email protected]2ff8b312010-04-26 22:20:547091
7092 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7093 EXPECT_EQ("hello!", response_data);
7094
[email protected]8e6441ca2010-08-19 05:56:387095 HttpStreamFactory::set_next_protos("");
7096 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]564b4912010-03-09 16:30:427097}
7098
[email protected]044de0642010-06-17 10:42:157099// GenerateAuthToken is a mighty big test.
7100// It tests all permutation of GenerateAuthToken behavior:
7101// - Synchronous and Asynchronous completion.
7102// - OK or error on completion.
7103// - Direct connection, non-authenticating proxy, and authenticating proxy.
7104// - HTTP or HTTPS backend (to include proxy tunneling).
7105// - Non-authenticating and authenticating backend.
7106//
7107// In all, there are 44 reasonable permuations (for example, if there are
7108// problems generating an auth token for an authenticating proxy, we don't
7109// need to test all permutations of the backend server).
7110//
7111// The test proceeds by going over each of the configuration cases, and
7112// potentially running up to three rounds in each of the tests. The TestConfig
7113// specifies both the configuration for the test as well as the expectations
7114// for the results.
7115TEST_F(HttpNetworkTransactionTest, GenerateAuthToken) {
[email protected]0b0bf032010-09-21 18:08:507116 static const char kServer[] = "http://www.example.com";
7117 static const char kSecureServer[] = "https://www.example.com";
7118 static const char kProxy[] = "myproxy:70";
[email protected]044de0642010-06-17 10:42:157119 const int kAuthErr = ERR_INVALID_AUTH_CREDENTIALS;
7120
7121 enum AuthTiming {
7122 AUTH_NONE,
7123 AUTH_SYNC,
7124 AUTH_ASYNC,
7125 };
7126
7127 const MockWrite kGet(
7128 "GET / HTTP/1.1\r\n"
7129 "Host: www.example.com\r\n"
7130 "Connection: keep-alive\r\n\r\n");
7131 const MockWrite kGetProxy(
7132 "GET http://www.example.com/ HTTP/1.1\r\n"
7133 "Host: www.example.com\r\n"
7134 "Proxy-Connection: keep-alive\r\n\r\n");
7135 const MockWrite kGetAuth(
7136 "GET / HTTP/1.1\r\n"
7137 "Host: www.example.com\r\n"
7138 "Connection: keep-alive\r\n"
7139 "Authorization: auth_token\r\n\r\n");
7140 const MockWrite kGetProxyAuth(
7141 "GET http://www.example.com/ HTTP/1.1\r\n"
7142 "Host: www.example.com\r\n"
7143 "Proxy-Connection: keep-alive\r\n"
7144 "Proxy-Authorization: auth_token\r\n\r\n");
7145 const MockWrite kGetAuthThroughProxy(
7146 "GET http://www.example.com/ HTTP/1.1\r\n"
7147 "Host: www.example.com\r\n"
7148 "Proxy-Connection: keep-alive\r\n"
7149 "Authorization: auth_token\r\n\r\n");
7150 const MockWrite kGetAuthWithProxyAuth(
7151 "GET http://www.example.com/ HTTP/1.1\r\n"
7152 "Host: www.example.com\r\n"
7153 "Proxy-Connection: keep-alive\r\n"
7154 "Proxy-Authorization: auth_token\r\n"
7155 "Authorization: auth_token\r\n\r\n");
7156 const MockWrite kConnect(
7157 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7158 "Host: www.example.com\r\n"
7159 "Proxy-Connection: keep-alive\r\n\r\n");
7160 const MockWrite kConnectProxyAuth(
7161 "CONNECT www.example.com:443 HTTP/1.1\r\n"
7162 "Host: www.example.com\r\n"
7163 "Proxy-Connection: keep-alive\r\n"
7164 "Proxy-Authorization: auth_token\r\n\r\n");
7165
7166 const MockRead kSuccess(
7167 "HTTP/1.1 200 OK\r\n"
7168 "Content-Type: text/html; charset=iso-8859-1\r\n"
7169 "Content-Length: 3\r\n\r\n"
7170 "Yes");
7171 const MockRead kFailure(
7172 "Should not be called.");
7173 const MockRead kServerChallenge(
7174 "HTTP/1.1 401 Unauthorized\r\n"
7175 "WWW-Authenticate: Mock realm=server\r\n"
7176 "Content-Type: text/html; charset=iso-8859-1\r\n"
7177 "Content-Length: 14\r\n\r\n"
7178 "Unauthorized\r\n");
7179 const MockRead kProxyChallenge(
7180 "HTTP/1.1 407 Unauthorized\r\n"
7181 "Proxy-Authenticate: Mock realm=proxy\r\n"
7182 "Proxy-Connection: close\r\n"
7183 "Content-Type: text/html; charset=iso-8859-1\r\n"
7184 "Content-Length: 14\r\n\r\n"
7185 "Unauthorized\r\n");
7186 const MockRead kProxyConnected(
7187 "HTTP/1.1 200 Connection Established\r\n\r\n");
7188
7189 // NOTE(cbentzel): I wanted TestReadWriteRound to be a simple struct with
7190 // no constructors, but the C++ compiler on Windows warns about
7191 // unspecified data in compound literals. So, moved to using constructors,
7192 // and TestRound's created with the default constructor should not be used.
7193 struct TestRound {
7194 TestRound()
7195 : expected_rv(ERR_UNEXPECTED),
7196 extra_write(NULL),
7197 extra_read(NULL) {
7198 }
7199 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7200 int expected_rv_arg)
7201 : write(write_arg),
7202 read(read_arg),
7203 expected_rv(expected_rv_arg),
7204 extra_write(NULL),
7205 extra_read(NULL) {
7206 }
7207 TestRound(const MockWrite& write_arg, const MockRead& read_arg,
7208 int expected_rv_arg, const MockWrite* extra_write_arg,
7209 const MockWrite* extra_read_arg)
7210 : write(write_arg),
7211 read(read_arg),
7212 expected_rv(expected_rv_arg),
7213 extra_write(extra_write_arg),
7214 extra_read(extra_read_arg) {
7215 }
7216 MockWrite write;
7217 MockRead read;
7218 int expected_rv;
7219 const MockWrite* extra_write;
7220 const MockRead* extra_read;
7221 };
7222
7223 static const int kNoSSL = 500;
7224
7225 struct TestConfig {
7226 const char* proxy_url;
7227 AuthTiming proxy_auth_timing;
7228 int proxy_auth_rv;
7229 const char* server_url;
7230 AuthTiming server_auth_timing;
7231 int server_auth_rv;
7232 int num_auth_rounds;
7233 int first_ssl_round;
7234 TestRound rounds[3];
7235 } test_configs[] = {
7236 // Non-authenticating HTTP server with a direct connection.
7237 { NULL, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7238 { TestRound(kGet, kSuccess, OK)}},
7239 // Authenticating HTTP server with a direct connection.
7240 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7241 { TestRound(kGet, kServerChallenge, OK),
7242 TestRound(kGetAuth, kSuccess, OK)}},
7243 { NULL, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7244 { TestRound(kGet, kServerChallenge, OK),
7245 TestRound(kGetAuth, kFailure, kAuthErr)}},
7246 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7247 { TestRound(kGet, kServerChallenge, OK),
7248 TestRound(kGetAuth, kSuccess, OK)}},
7249 { NULL, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7250 { TestRound(kGet, kServerChallenge, OK),
7251 TestRound(kGetAuth, kFailure, kAuthErr)}},
7252 // Non-authenticating HTTP server through a non-authenticating proxy.
7253 { kProxy, AUTH_NONE, OK, kServer, AUTH_NONE, OK, 1, kNoSSL,
7254 { TestRound(kGetProxy, kSuccess, OK)}},
7255 // Authenticating HTTP server through a non-authenticating proxy.
7256 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, OK, 2, kNoSSL,
7257 { TestRound(kGetProxy, kServerChallenge, OK),
7258 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7259 { kProxy, AUTH_NONE, OK, kServer, AUTH_SYNC, kAuthErr, 2, kNoSSL,
7260 { TestRound(kGetProxy, kServerChallenge, OK),
7261 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7262 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, OK, 2, kNoSSL,
7263 { TestRound(kGetProxy, kServerChallenge, OK),
7264 TestRound(kGetAuthThroughProxy, kSuccess, OK)}},
7265 { kProxy, AUTH_NONE, OK, kServer, AUTH_ASYNC, kAuthErr, 2, kNoSSL,
7266 { TestRound(kGetProxy, kServerChallenge, OK),
7267 TestRound(kGetAuthThroughProxy, kFailure, kAuthErr)}},
7268 // Non-authenticating HTTP server through an authenticating proxy.
7269 { kProxy, AUTH_SYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7270 { TestRound(kGetProxy, kProxyChallenge, OK),
7271 TestRound(kGetProxyAuth, kSuccess, OK)}},
7272 { kProxy, AUTH_SYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7273 { TestRound(kGetProxy, kProxyChallenge, OK),
7274 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7275 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_NONE, OK, 2, kNoSSL,
7276 { TestRound(kGetProxy, kProxyChallenge, OK),
7277 TestRound(kGetProxyAuth, kSuccess, OK)}},
7278 { kProxy, AUTH_ASYNC, kAuthErr, kServer, AUTH_NONE, OK, 2, kNoSSL,
7279 { TestRound(kGetProxy, kProxyChallenge, OK),
7280 TestRound(kGetProxyAuth, kFailure, kAuthErr)}},
7281 // Authenticating HTTP server through an authenticating proxy.
7282 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7283 { TestRound(kGetProxy, kProxyChallenge, OK),
7284 TestRound(kGetProxyAuth, kServerChallenge, OK),
7285 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7286 { kProxy, AUTH_SYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7287 { TestRound(kGetProxy, kProxyChallenge, OK),
7288 TestRound(kGetProxyAuth, kServerChallenge, OK),
7289 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7290 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, OK, 3, kNoSSL,
7291 { TestRound(kGetProxy, kProxyChallenge, OK),
7292 TestRound(kGetProxyAuth, kServerChallenge, OK),
7293 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7294 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_SYNC, kAuthErr, 3, kNoSSL,
7295 { TestRound(kGetProxy, kProxyChallenge, OK),
7296 TestRound(kGetProxyAuth, kServerChallenge, OK),
7297 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7298 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7299 { TestRound(kGetProxy, kProxyChallenge, OK),
7300 TestRound(kGetProxyAuth, kServerChallenge, OK),
7301 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7302 { kProxy, AUTH_SYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7303 { TestRound(kGetProxy, kProxyChallenge, OK),
7304 TestRound(kGetProxyAuth, kServerChallenge, OK),
7305 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7306 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, OK, 3, kNoSSL,
7307 { TestRound(kGetProxy, kProxyChallenge, OK),
7308 TestRound(kGetProxyAuth, kServerChallenge, OK),
7309 TestRound(kGetAuthWithProxyAuth, kSuccess, OK)}},
7310 { kProxy, AUTH_ASYNC, OK, kServer, AUTH_ASYNC, kAuthErr, 3, kNoSSL,
7311 { TestRound(kGetProxy, kProxyChallenge, OK),
7312 TestRound(kGetProxyAuth, kServerChallenge, OK),
7313 TestRound(kGetAuthWithProxyAuth, kFailure, kAuthErr)}},
7314 // Non-authenticating HTTPS server with a direct connection.
7315 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7316 { TestRound(kGet, kSuccess, OK)}},
7317 // Authenticating HTTPS server with a direct connection.
7318 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7319 { TestRound(kGet, kServerChallenge, OK),
7320 TestRound(kGetAuth, kSuccess, OK)}},
7321 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7322 { TestRound(kGet, kServerChallenge, OK),
7323 TestRound(kGetAuth, kFailure, kAuthErr)}},
7324 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7325 { TestRound(kGet, kServerChallenge, OK),
7326 TestRound(kGetAuth, kSuccess, OK)}},
7327 { NULL, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7328 { TestRound(kGet, kServerChallenge, OK),
7329 TestRound(kGetAuth, kFailure, kAuthErr)}},
7330 // Non-authenticating HTTPS server with a non-authenticating proxy.
7331 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_NONE, OK, 1, 0,
7332 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kSuccess)}},
7333 // Authenticating HTTPS server through a non-authenticating proxy.
7334 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, OK, 2, 0,
7335 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7336 TestRound(kGetAuth, kSuccess, OK)}},
7337 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_SYNC, kAuthErr, 2, 0,
7338 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7339 TestRound(kGetAuth, kFailure, kAuthErr)}},
7340 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, OK, 2, 0,
7341 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7342 TestRound(kGetAuth, kSuccess, OK)}},
7343 { kProxy, AUTH_NONE, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 2, 0,
7344 { TestRound(kConnect, kProxyConnected, OK, &kGet, &kServerChallenge),
7345 TestRound(kGetAuth, kFailure, kAuthErr)}},
7346 // Non-Authenticating HTTPS server through an authenticating proxy.
7347 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7348 { TestRound(kConnect, kProxyChallenge, OK),
7349 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7350 { kProxy, AUTH_SYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7351 { TestRound(kConnect, kProxyChallenge, OK),
7352 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7353 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_NONE, OK, 2, 1,
7354 { TestRound(kConnect, kProxyChallenge, OK),
7355 TestRound(kConnectProxyAuth, kProxyConnected, OK, &kGet, &kSuccess)}},
7356 { kProxy, AUTH_ASYNC, kAuthErr, kSecureServer, AUTH_NONE, OK, 2, kNoSSL,
7357 { TestRound(kConnect, kProxyChallenge, OK),
7358 TestRound(kConnectProxyAuth, kFailure, kAuthErr)}},
7359 // Authenticating HTTPS server through an authenticating proxy.
7360 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7361 { TestRound(kConnect, kProxyChallenge, OK),
7362 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7363 &kGet, &kServerChallenge),
7364 TestRound(kGetAuth, kSuccess, OK)}},
7365 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7366 { TestRound(kConnect, kProxyChallenge, OK),
7367 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7368 &kGet, &kServerChallenge),
7369 TestRound(kGetAuth, kFailure, kAuthErr)}},
7370 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, OK, 3, 1,
7371 { TestRound(kConnect, kProxyChallenge, OK),
7372 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7373 &kGet, &kServerChallenge),
7374 TestRound(kGetAuth, kSuccess, OK)}},
7375 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_SYNC, kAuthErr, 3, 1,
7376 { TestRound(kConnect, kProxyChallenge, OK),
7377 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7378 &kGet, &kServerChallenge),
7379 TestRound(kGetAuth, kFailure, kAuthErr)}},
7380 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7381 { TestRound(kConnect, kProxyChallenge, OK),
7382 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7383 &kGet, &kServerChallenge),
7384 TestRound(kGetAuth, kSuccess, OK)}},
7385 { kProxy, AUTH_SYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7386 { TestRound(kConnect, kProxyChallenge, OK),
7387 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7388 &kGet, &kServerChallenge),
7389 TestRound(kGetAuth, kFailure, kAuthErr)}},
7390 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, OK, 3, 1,
7391 { TestRound(kConnect, kProxyChallenge, OK),
7392 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7393 &kGet, &kServerChallenge),
7394 TestRound(kGetAuth, kSuccess, OK)}},
7395 { kProxy, AUTH_ASYNC, OK, kSecureServer, AUTH_ASYNC, kAuthErr, 3, 1,
7396 { TestRound(kConnect, kProxyChallenge, OK),
7397 TestRound(kConnectProxyAuth, kProxyConnected, OK,
7398 &kGet, &kServerChallenge),
7399 TestRound(kGetAuth, kFailure, kAuthErr)}},
7400 };
7401
7402 SessionDependencies session_deps;
[email protected]3fd9dae2010-06-21 11:39:007403 HttpAuthHandlerMock::Factory* auth_factory(
7404 new HttpAuthHandlerMock::Factory());
[email protected]044de0642010-06-17 10:42:157405 session_deps.http_auth_handler_factory.reset(auth_factory);
7406
7407 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_configs); ++i) {
7408 const TestConfig& test_config = test_configs[i];
[email protected]65d34382010-07-01 18:12:267409
7410 // Set up authentication handlers as necessary.
[email protected]044de0642010-06-17 10:42:157411 if (test_config.proxy_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007412 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157413 std::string auth_challenge = "Mock realm=proxy";
7414 GURL origin(test_config.proxy_url);
7415 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7416 auth_challenge.end());
7417 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_PROXY,
7418 origin, BoundNetLog());
7419 auth_handler->SetGenerateExpectation(
7420 test_config.proxy_auth_timing == AUTH_ASYNC,
7421 test_config.proxy_auth_rv);
[email protected]044de0642010-06-17 10:42:157422 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7423 }
7424 if (test_config.server_auth_timing != AUTH_NONE) {
[email protected]3fd9dae2010-06-21 11:39:007425 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
[email protected]044de0642010-06-17 10:42:157426 std::string auth_challenge = "Mock realm=server";
7427 GURL origin(test_config.server_url);
7428 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7429 auth_challenge.end());
7430 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7431 origin, BoundNetLog());
7432 auth_handler->SetGenerateExpectation(
7433 test_config.server_auth_timing == AUTH_ASYNC,
7434 test_config.server_auth_rv);
[email protected]044de0642010-06-17 10:42:157435 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7436 }
7437 if (test_config.proxy_url) {
[email protected]6104ea5d2011-04-27 21:37:127438 session_deps.proxy_service.reset(
7439 ProxyService::CreateFixed(test_config.proxy_url));
[email protected]044de0642010-06-17 10:42:157440 } else {
[email protected]6104ea5d2011-04-27 21:37:127441 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]044de0642010-06-17 10:42:157442 }
7443
7444 HttpRequestInfo request;
7445 request.method = "GET";
7446 request.url = GURL(test_config.server_url);
7447 request.load_flags = 0;
7448
[email protected]0b0bf032010-09-21 18:08:507449 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7450 HttpNetworkTransaction trans(CreateSession(&session_deps));
[email protected]044de0642010-06-17 10:42:157451
7452 for (int round = 0; round < test_config.num_auth_rounds; ++round) {
7453 const TestRound& read_write_round = test_config.rounds[round];
7454
7455 // Set up expected reads and writes.
7456 MockRead reads[2];
7457 reads[0] = read_write_round.read;
7458 size_t length_reads = 1;
7459 if (read_write_round.extra_read) {
7460 reads[1] = *read_write_round.extra_read;
7461 length_reads = 2;
7462 }
7463
7464 MockWrite writes[2];
7465 writes[0] = read_write_round.write;
7466 size_t length_writes = 1;
7467 if (read_write_round.extra_write) {
7468 writes[1] = *read_write_round.extra_write;
7469 length_writes = 2;
7470 }
7471 StaticSocketDataProvider data_provider(
7472 reads, length_reads, writes, length_writes);
7473 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7474
7475 // Add an SSL sequence if necessary.
7476 SSLSocketDataProvider ssl_socket_data_provider(false, OK);
7477 if (round >= test_config.first_ssl_round)
7478 session_deps.socket_factory.AddSSLSocketDataProvider(
7479 &ssl_socket_data_provider);
7480
7481 // Start or restart the transaction.
7482 TestCompletionCallback callback;
7483 int rv;
7484 if (round == 0) {
[email protected]0b0bf032010-09-21 18:08:507485 rv = trans.Start(&request, &callback, BoundNetLog());
[email protected]044de0642010-06-17 10:42:157486 } else {
[email protected]0b0bf032010-09-21 18:08:507487 rv = trans.RestartWithAuth(kFoo, kBar, &callback);
[email protected]044de0642010-06-17 10:42:157488 }
7489 if (rv == ERR_IO_PENDING)
7490 rv = callback.WaitForResult();
7491
7492 // Compare results with expected data.
7493 EXPECT_EQ(read_write_round.expected_rv, rv);
[email protected]0b0bf032010-09-21 18:08:507494 const HttpResponseInfo* response = trans.GetResponseInfo();
[email protected]044de0642010-06-17 10:42:157495 if (read_write_round.expected_rv == OK) {
7496 EXPECT_FALSE(response == NULL);
7497 } else {
7498 EXPECT_TRUE(response == NULL);
7499 EXPECT_EQ(round + 1, test_config.num_auth_rounds);
7500 continue;
7501 }
7502 if (round + 1 < test_config.num_auth_rounds) {
7503 EXPECT_FALSE(response->auth_challenge.get() == NULL);
7504 } else {
7505 EXPECT_TRUE(response->auth_challenge.get() == NULL);
7506 }
7507 }
[email protected]e5ae96a2010-04-14 20:12:457508 }
7509}
7510
[email protected]c871bce92010-07-15 21:51:147511TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
7512 // Do multi-round authentication and make sure it works correctly.
7513 SessionDependencies session_deps;
7514 HttpAuthHandlerMock::Factory* auth_factory(
7515 new HttpAuthHandlerMock::Factory());
7516 session_deps.http_auth_handler_factory.reset(auth_factory);
[email protected]6104ea5d2011-04-27 21:37:127517 session_deps.proxy_service.reset(ProxyService::CreateDirect());
[email protected]c871bce92010-07-15 21:51:147518 session_deps.host_resolver->rules()->AddRule("www.example.com", "10.0.0.1");
7519 session_deps.host_resolver->set_synchronous_mode(true);
7520
7521 HttpAuthHandlerMock* auth_handler(new HttpAuthHandlerMock());
7522 auth_handler->set_connection_based(true);
7523 std::string auth_challenge = "Mock realm=server";
7524 GURL origin("http://www.example.com");
7525 HttpAuth::ChallengeTokenizer tokenizer(auth_challenge.begin(),
7526 auth_challenge.end());
7527 auth_handler->InitFromChallenge(&tokenizer, HttpAuth::AUTH_SERVER,
7528 origin, BoundNetLog());
7529 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_SERVER);
7530
[email protected]c871bce92010-07-15 21:51:147531 int rv = OK;
7532 const HttpResponseInfo* response = NULL;
7533 HttpRequestInfo request;
7534 request.method = "GET";
7535 request.url = origin;
7536 request.load_flags = 0;
[email protected]cb9bf6ca2011-01-28 13:15:277537
7538 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
[email protected]7ef4cbbb2011-02-06 11:19:107539
7540 // Use a TCP Socket Pool with only one connection per group. This is used
7541 // to validate that the TCP socket is not released to the pool between
7542 // each round of multi-round authentication.
7543 HttpNetworkSessionPeer session_peer(session);
[email protected]ab739042011-04-07 15:22:287544 ClientSocketPoolHistograms transport_pool_histograms("SmallTCP");
7545 TransportClientSocketPool* transport_pool = new TransportClientSocketPool(
[email protected]7ef4cbbb2011-02-06 11:19:107546 50, // Max sockets for pool
7547 1, // Max sockets per group
[email protected]ab739042011-04-07 15:22:287548 &transport_pool_histograms,
[email protected]7ef4cbbb2011-02-06 11:19:107549 session_deps.host_resolver.get(),
7550 &session_deps.socket_factory,
7551 session_deps.net_log);
[email protected]ab739042011-04-07 15:22:287552 session_peer.SetTransportSocketPool(transport_pool);
[email protected]7ef4cbbb2011-02-06 11:19:107553
[email protected]cb9bf6ca2011-01-28 13:15:277554 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
[email protected]c871bce92010-07-15 21:51:147555 TestCompletionCallback callback;
7556
7557 const MockWrite kGet(
7558 "GET / HTTP/1.1\r\n"
7559 "Host: www.example.com\r\n"
7560 "Connection: keep-alive\r\n\r\n");
7561 const MockWrite kGetAuth(
7562 "GET / HTTP/1.1\r\n"
7563 "Host: www.example.com\r\n"
7564 "Connection: keep-alive\r\n"
7565 "Authorization: auth_token\r\n\r\n");
7566
7567 const MockRead kServerChallenge(
7568 "HTTP/1.1 401 Unauthorized\r\n"
7569 "WWW-Authenticate: Mock realm=server\r\n"
7570 "Content-Type: text/html; charset=iso-8859-1\r\n"
7571 "Content-Length: 14\r\n\r\n"
7572 "Unauthorized\r\n");
7573 const MockRead kSuccess(
7574 "HTTP/1.1 200 OK\r\n"
7575 "Content-Type: text/html; charset=iso-8859-1\r\n"
7576 "Content-Length: 3\r\n\r\n"
7577 "Yes");
7578
7579 MockWrite writes[] = {
7580 // First round
7581 kGet,
7582 // Second round
7583 kGetAuth,
7584 // Third round
7585 kGetAuth,
[email protected]eca50e122010-09-11 14:03:307586 // Fourth round
[email protected]7ef4cbbb2011-02-06 11:19:107587 kGetAuth,
7588 // Competing request
7589 kGet,
[email protected]c871bce92010-07-15 21:51:147590 };
7591 MockRead reads[] = {
7592 // First round
7593 kServerChallenge,
7594 // Second round
7595 kServerChallenge,
7596 // Third round
[email protected]eca50e122010-09-11 14:03:307597 kServerChallenge,
7598 // Fourth round
[email protected]c871bce92010-07-15 21:51:147599 kSuccess,
[email protected]7ef4cbbb2011-02-06 11:19:107600 // Competing response
7601 kSuccess,
[email protected]c871bce92010-07-15 21:51:147602 };
7603 StaticSocketDataProvider data_provider(reads, arraysize(reads),
7604 writes, arraysize(writes));
7605 session_deps.socket_factory.AddSocketDataProvider(&data_provider);
7606
[email protected]7ef4cbbb2011-02-06 11:19:107607 const char* const kSocketGroup = "www.example.com:80";
7608
7609 // First round of authentication.
[email protected]c871bce92010-07-15 21:51:147610 auth_handler->SetGenerateExpectation(false, OK);
7611 rv = trans->Start(&request, &callback, BoundNetLog());
7612 if (rv == ERR_IO_PENDING)
7613 rv = callback.WaitForResult();
7614 EXPECT_EQ(OK, rv);
7615 response = trans->GetResponseInfo();
7616 ASSERT_FALSE(response == NULL);
7617 EXPECT_FALSE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287618 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147619
[email protected]7ef4cbbb2011-02-06 11:19:107620 // In between rounds, another request comes in for the same domain.
7621 // It should not be able to grab the TCP socket that trans has already
7622 // claimed.
7623 scoped_ptr<HttpTransaction> trans_compete(
7624 new HttpNetworkTransaction(session));
7625 TestCompletionCallback callback_compete;
7626 rv = trans_compete->Start(&request, &callback_compete, BoundNetLog());
7627 EXPECT_EQ(ERR_IO_PENDING, rv);
7628 // callback_compete.WaitForResult at this point would stall forever,
7629 // since the HttpNetworkTransaction does not release the request back to
7630 // the pool until after authentication completes.
7631
7632 // Second round of authentication.
[email protected]c871bce92010-07-15 21:51:147633 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447634 rv = trans->RestartWithAuth(kFoo, kBar, &callback);
[email protected]c871bce92010-07-15 21:51:147635 if (rv == ERR_IO_PENDING)
7636 rv = callback.WaitForResult();
7637 EXPECT_EQ(OK, rv);
7638 response = trans->GetResponseInfo();
7639 ASSERT_FALSE(response == NULL);
7640 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287641 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147642
[email protected]7ef4cbbb2011-02-06 11:19:107643 // Third round of authentication.
[email protected]c871bce92010-07-15 21:51:147644 auth_handler->SetGenerateExpectation(false, OK);
[email protected]13c8a092010-07-29 06:15:447645 rv = trans->RestartWithAuth(string16(), string16(), &callback);
[email protected]c871bce92010-07-15 21:51:147646 if (rv == ERR_IO_PENDING)
7647 rv = callback.WaitForResult();
7648 EXPECT_EQ(OK, rv);
7649 response = trans->GetResponseInfo();
7650 ASSERT_FALSE(response == NULL);
7651 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287652 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]eca50e122010-09-11 14:03:307653
[email protected]7ef4cbbb2011-02-06 11:19:107654 // Fourth round of authentication, which completes successfully.
[email protected]eca50e122010-09-11 14:03:307655 auth_handler->SetGenerateExpectation(false, OK);
7656 rv = trans->RestartWithAuth(string16(), string16(), &callback);
7657 if (rv == ERR_IO_PENDING)
7658 rv = callback.WaitForResult();
7659 EXPECT_EQ(OK, rv);
7660 response = trans->GetResponseInfo();
7661 ASSERT_FALSE(response == NULL);
7662 EXPECT_TRUE(response->auth_challenge.get() == NULL);
[email protected]ab739042011-04-07 15:22:287663 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107664
7665 // Read the body since the fourth round was successful. This will also
7666 // release the socket back to the pool.
7667 scoped_refptr<IOBufferWithSize> io_buf(new IOBufferWithSize(50));
7668 rv = trans->Read(io_buf, io_buf->size(), &callback);
7669 if (rv == ERR_IO_PENDING)
7670 rv = callback.WaitForResult();
7671 EXPECT_EQ(3, rv);
7672 rv = trans->Read(io_buf, io_buf->size(), &callback);
7673 EXPECT_EQ(0, rv);
7674 // There are still 0 idle sockets, since the trans_compete transaction
7675 // will be handed it immediately after trans releases it to the group.
[email protected]ab739042011-04-07 15:22:287676 EXPECT_EQ(0, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]7ef4cbbb2011-02-06 11:19:107677
7678 // The competing request can now finish. Wait for the headers and then
7679 // read the body.
7680 rv = callback_compete.WaitForResult();
7681 EXPECT_EQ(OK, rv);
7682 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7683 if (rv == ERR_IO_PENDING)
7684 rv = callback.WaitForResult();
7685 EXPECT_EQ(3, rv);
7686 rv = trans_compete->Read(io_buf, io_buf->size(), &callback);
7687 EXPECT_EQ(0, rv);
7688
7689 // Finally, the socket is released to the group.
[email protected]ab739042011-04-07 15:22:287690 EXPECT_EQ(1, transport_pool->IdleSocketCountInGroup(kSocketGroup));
[email protected]c871bce92010-07-15 21:51:147691}
7692
[email protected]aeaca1f2010-04-20 22:05:217693class TLSDecompressionFailureSocketDataProvider : public SocketDataProvider {
7694 public:
[email protected]06650c52010-06-03 00:49:177695 explicit TLSDecompressionFailureSocketDataProvider(bool fail_all)
[email protected]aeaca1f2010-04-20 22:05:217696 : fail_all_(fail_all) {
7697 }
7698
7699 virtual MockRead GetNextRead() {
7700 if (fail_all_)
7701 return MockRead(false /* async */, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
7702
7703 return MockRead(false /* async */,
7704 "HTTP/1.1 200 OK\r\nContent-Length: 3\r\n\r\nok.\r\n");
7705 }
7706
7707 virtual MockWriteResult OnWrite(const std::string& data) {
7708 return MockWriteResult(false /* async */, data.size());
7709 }
7710
7711 void Reset() {
7712 }
7713
7714 private:
7715 const bool fail_all_;
7716};
7717
7718// Test that we restart a connection when we see a decompression failure from
7719// the peer during the handshake. (In the real world we'll restart with SSLv3
7720// and we won't offer DEFLATE in that case.)
7721TEST_F(HttpNetworkTransactionTest, RestartAfterTLSDecompressionFailure) {
7722 HttpRequestInfo request;
7723 request.method = "GET";
7724 request.url = GURL("https://tlsdecompressionfailure.example.com/");
7725 request.load_flags = 0;
7726
7727 SessionDependencies session_deps;
7728 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7729 false /* fail all reads */);
7730 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7731 SSLSocketDataProvider ssl_socket_data_provider1(
[email protected]2227c692010-05-04 15:36:117732 false, ERR_SSL_DECOMPRESSION_FAILURE_ALERT);
[email protected]aeaca1f2010-04-20 22:05:217733 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7734 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7735 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7736 session_deps.socket_factory.AddSSLSocketDataProvider(
7737 &ssl_socket_data_provider1);
7738 session_deps.socket_factory.AddSSLSocketDataProvider(
7739 &ssl_socket_data_provider2);
7740
[email protected]e60e47a2010-07-14 03:37:187741 // Work around http://crbug.com/37454
7742 StaticSocketDataProvider bug37454_connection;
7743 bug37454_connection.set_connect_data(MockConnect(true, ERR_UNEXPECTED));
7744 session_deps.socket_factory.AddSocketDataProvider(&bug37454_connection);
7745
[email protected]aeaca1f2010-04-20 22:05:217746 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7747 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7748 TestCompletionCallback callback;
7749
[email protected]5a1d7ca2010-04-28 20:12:277750 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217751 EXPECT_EQ(ERR_IO_PENDING, rv);
7752 EXPECT_EQ(OK, callback.WaitForResult());
7753
7754 const HttpResponseInfo* response = trans->GetResponseInfo();
7755 ASSERT_TRUE(response != NULL);
7756 ASSERT_TRUE(response->headers != NULL);
7757 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7758
7759 std::string response_data;
7760 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7761 EXPECT_EQ("ok.", response_data);
7762}
7763
7764// Test that we restart a connection if we get a decompression failure from the
7765// peer while reading the first bytes from the connection. This occurs when the
7766// peer cannot handle DEFLATE but we're using False Start, so we don't notice
7767// in the handshake.
7768TEST_F(HttpNetworkTransactionTest,
7769 RestartAfterTLSDecompressionFailureWithFalseStart) {
7770 HttpRequestInfo request;
7771 request.method = "GET";
7772 request.url = GURL("https://tlsdecompressionfailure2.example.com/");
7773 request.load_flags = 0;
7774
7775 SessionDependencies session_deps;
7776 TLSDecompressionFailureSocketDataProvider socket_data_provider1(
7777 true /* fail all reads */);
7778 TLSDecompressionFailureSocketDataProvider socket_data_provider2(false);
7779 SSLSocketDataProvider ssl_socket_data_provider1(false, OK);
7780 SSLSocketDataProvider ssl_socket_data_provider2(false, OK);
7781 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider1);
7782 session_deps.socket_factory.AddSocketDataProvider(&socket_data_provider2);
7783 session_deps.socket_factory.AddSSLSocketDataProvider(
7784 &ssl_socket_data_provider1);
7785 session_deps.socket_factory.AddSSLSocketDataProvider(
7786 &ssl_socket_data_provider2);
7787
7788 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7789 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7790 TestCompletionCallback callback;
7791
[email protected]5a1d7ca2010-04-28 20:12:277792 int rv = trans->Start(&request, &callback, BoundNetLog());
[email protected]aeaca1f2010-04-20 22:05:217793 EXPECT_EQ(ERR_IO_PENDING, rv);
7794 EXPECT_EQ(OK, callback.WaitForResult());
7795
7796 const HttpResponseInfo* response = trans->GetResponseInfo();
7797 ASSERT_TRUE(response != NULL);
7798 ASSERT_TRUE(response->headers != NULL);
7799 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7800
7801 std::string response_data;
7802 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7803 EXPECT_EQ("ok.", response_data);
7804}
7805
[email protected]65041fa2010-05-21 06:56:537806// This tests the case that a request is issued via http instead of spdy after
7807// npn is negotiated.
7808TEST_F(HttpNetworkTransactionTest, NpnWithHttpOverSSL) {
[email protected]8e6441ca2010-08-19 05:56:387809 HttpStreamFactory::set_use_alternate_protocols(true);
7810 HttpStreamFactory::set_next_protos("\x08http/1.1\x07http1.1");
[email protected]65041fa2010-05-21 06:56:537811 SessionDependencies session_deps;
7812 HttpRequestInfo request;
7813 request.method = "GET";
7814 request.url = GURL("https://www.google.com/");
7815 request.load_flags = 0;
7816
7817 MockWrite data_writes[] = {
7818 MockWrite("GET / HTTP/1.1\r\n"
7819 "Host: www.google.com\r\n"
7820 "Connection: keep-alive\r\n\r\n"),
7821 };
7822
7823 MockRead data_reads[] = {
7824 MockRead("HTTP/1.1 200 OK\r\n"),
[email protected]dae22c52010-07-30 02:16:357825 MockRead(kAlternateProtocolHttpHeader),
[email protected]65041fa2010-05-21 06:56:537826 MockRead("hello world"),
7827 MockRead(false, OK),
7828 };
7829
7830 SSLSocketDataProvider ssl(true, OK);
7831 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
7832 ssl.next_proto = "http/1.1";
7833
7834 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7835
7836 StaticSocketDataProvider data(data_reads, arraysize(data_reads),
7837 data_writes, arraysize(data_writes));
7838 session_deps.socket_factory.AddSocketDataProvider(&data);
7839
7840 TestCompletionCallback callback;
7841
7842 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7843 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
7844
7845 int rv = trans->Start(&request, &callback, BoundNetLog());
7846
7847 EXPECT_EQ(ERR_IO_PENDING, rv);
7848 EXPECT_EQ(OK, callback.WaitForResult());
7849
7850 const HttpResponseInfo* response = trans->GetResponseInfo();
7851 ASSERT_TRUE(response != NULL);
7852 ASSERT_TRUE(response->headers != NULL);
7853 EXPECT_EQ("HTTP/1.1 200 OK", response->headers->GetStatusLine());
7854
7855 std::string response_data;
7856 ASSERT_EQ(OK, ReadTransaction(trans.get(), &response_data));
7857 EXPECT_EQ("hello world", response_data);
7858
7859 EXPECT_FALSE(response->was_fetched_via_spdy);
7860 EXPECT_TRUE(response->was_npn_negotiated);
7861
[email protected]8e6441ca2010-08-19 05:56:387862 HttpStreamFactory::set_next_protos("");
7863 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]65041fa2010-05-21 06:56:537864}
[email protected]26ef6582010-06-24 02:30:477865
7866TEST_F(HttpNetworkTransactionTest, SpdyPostNPNServerHangup) {
7867 // Simulate the SSL handshake completing with an NPN negotiation
7868 // followed by an immediate server closing of the socket.
7869 // Fix crash: http://crbug.com/46369
[email protected]8e6441ca2010-08-19 05:56:387870 HttpStreamFactory::set_use_alternate_protocols(true);
7871 HttpStreamFactory::set_next_protos(kExpectedNPNString);
[email protected]26ef6582010-06-24 02:30:477872 SessionDependencies session_deps;
7873
7874 HttpRequestInfo request;
7875 request.method = "GET";
7876 request.url = GURL("https://www.google.com/");
7877 request.load_flags = 0;
7878
7879 SSLSocketDataProvider ssl(true, OK);
7880 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
[email protected]dae22c52010-07-30 02:16:357881 ssl.next_proto = "spdy/2";
[email protected]26ef6582010-06-24 02:30:477882 ssl.was_npn_negotiated = true;
7883 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
7884
[email protected]2bd93022010-07-17 00:58:447885 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
[email protected]e7f75092010-07-01 22:39:137886 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
[email protected]26ef6582010-06-24 02:30:477887
7888 MockRead spdy_reads[] = {
7889 MockRead(false, 0, 0) // Not async - return 0 immediately.
7890 };
7891
7892 scoped_refptr<DelayedSocketData> spdy_data(
7893 new DelayedSocketData(
7894 0, // don't wait in this case, immediate hangup.
7895 spdy_reads, arraysize(spdy_reads),
7896 spdy_writes, arraysize(spdy_writes)));
7897 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
7898
7899 TestCompletionCallback callback;
7900
7901 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
7902 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
7903
7904 int rv = trans->Start(&request, &callback, BoundNetLog());
7905 EXPECT_EQ(ERR_IO_PENDING, rv);
7906 EXPECT_EQ(ERR_CONNECTION_CLOSED, callback.WaitForResult());
7907
[email protected]8e6441ca2010-08-19 05:56:387908 HttpStreamFactory::set_next_protos("");
7909 HttpStreamFactory::set_use_alternate_protocols(false);
[email protected]26ef6582010-06-24 02:30:477910}
[email protected]65d34382010-07-01 18:12:267911
[email protected]f45c1ee2010-08-03 00:54:307912TEST_F(HttpNetworkTransactionTest, SpdyAlternateProtocolThroughProxy) {
7913 // This test ensures that the URL passed into the proxy is upgraded
7914 // to https when doing an Alternate Protocol upgrade.
[email protected]8e6441ca2010-08-19 05:56:387915 HttpStreamFactory::set_use_alternate_protocols(true);
7916 HttpStreamFactory::set_next_protos(
[email protected]f45c1ee2010-08-03 00:54:307917 "\x08http/1.1\x07http1.1\x06spdy/2\x04spdy");
7918
[email protected]81cdfcd2010-10-16 00:49:007919 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]f45c1ee2010-08-03 00:54:307920 HttpAuthHandlerMock::Factory* auth_factory =
7921 new HttpAuthHandlerMock::Factory();
7922 HttpAuthHandlerMock* auth_handler = new HttpAuthHandlerMock();
7923 auth_factory->set_mock_handler(auth_handler, HttpAuth::AUTH_PROXY);
7924 auth_factory->set_do_init_from_challenge(true);
7925 session_deps.http_auth_handler_factory.reset(auth_factory);
7926
7927 HttpRequestInfo request;
7928 request.method = "GET";
7929 request.url = GURL("http://www.google.com");
7930 request.load_flags = 0;
7931
7932 // First round goes unauthenticated through the proxy.
7933 MockWrite data_writes_1[] = {
7934 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
7935 "Host: www.google.com\r\n"
7936 "Proxy-Connection: keep-alive\r\n"
7937 "\r\n"),
7938 };
7939 MockRead data_reads_1[] = {
[email protected]394816e92010-08-03 07:38:597940 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
[email protected]f45c1ee2010-08-03 00:54:307941 MockRead("HTTP/1.1 200 OK\r\n"
7942 "Alternate-Protocol: 443:npn-spdy/2\r\n"
7943 "Proxy-Connection: close\r\n"
7944 "\r\n"),
7945 };
7946 StaticSocketDataProvider data_1(data_reads_1, arraysize(data_reads_1),
7947 data_writes_1, arraysize(data_writes_1));
7948
7949 // Second round tries to tunnel to www.google.com due to the
7950 // Alternate-Protocol announcement in the first round. It fails due
7951 // to a proxy authentication challenge.
[email protected]394816e92010-08-03 07:38:597952 // After the failure, a tunnel is established to www.google.com using
7953 // Proxy-Authorization headers. There is then a SPDY request round.
7954 //
7955 // NOTE: Despite the "Proxy-Connection: Close", these are done on the
7956 // same MockTCPClientSocket since the underlying HttpNetworkClientSocket
7957 // does a Disconnect and Connect on the same socket, rather than trying
7958 // to obtain a new one.
7959 //
7960 // NOTE: Originally, the proxy response to the second CONNECT request
7961 // simply returned another 407 so the unit test could skip the SSL connection
7962 // establishment and SPDY framing issues. Alas, the
7963 // retry-http-when-alternate-protocol fails logic kicks in, which was more
[email protected]f45c1ee2010-08-03 00:54:307964 // complicated to set up expectations for than the SPDY session.
[email protected]394816e92010-08-03 07:38:597965
[email protected]f45c1ee2010-08-03 00:54:307966 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(NULL, 0, false, 1, LOWEST));
7967 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
7968 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
7969
[email protected]394816e92010-08-03 07:38:597970 MockWrite data_writes_2[] = {
7971 // First connection attempt without Proxy-Authorization.
7972 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7973 "Host: www.google.com\r\n"
7974 "Proxy-Connection: keep-alive\r\n"
7975 "\r\n"),
7976
7977 // Second connection attempt with Proxy-Authorization.
[email protected]f45c1ee2010-08-03 00:54:307978 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
7979 "Host: www.google.com\r\n"
7980 "Proxy-Connection: keep-alive\r\n"
7981 "Proxy-Authorization: auth_token\r\n"
7982 "\r\n"),
[email protected]f45c1ee2010-08-03 00:54:307983
[email protected]394816e92010-08-03 07:38:597984 // SPDY request
7985 CreateMockWrite(*req),
[email protected]f45c1ee2010-08-03 00:54:307986 };
[email protected]394816e92010-08-03 07:38:597987 const char kRejectConnectResponse[] = ("HTTP/1.1 407 Unauthorized\r\n"
7988 "Proxy-Authenticate: Mock\r\n"
7989 "Proxy-Connection: close\r\n"
7990 "\r\n");
7991 const char kAcceptConnectResponse[] = "HTTP/1.1 200 Connected\r\n\r\n";
7992 MockRead data_reads_2[] = {
7993 // First connection attempt fails
7994 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ, 1),
7995 MockRead(true, kRejectConnectResponse,
7996 arraysize(kRejectConnectResponse) - 1, 1),
7997
7998 // Second connection attempt passes
7999 MockRead(true, kAcceptConnectResponse,
8000 arraysize(kAcceptConnectResponse) -1, 4),
8001
8002 // SPDY response
8003 CreateMockRead(*resp.get(), 6),
8004 CreateMockRead(*data.get(), 6),
8005 MockRead(true, 0, 0, 6),
8006 };
8007 scoped_refptr<OrderedSocketData> data_2(
8008 new OrderedSocketData(data_reads_2, arraysize(data_reads_2),
8009 data_writes_2, arraysize(data_writes_2)));
[email protected]f45c1ee2010-08-03 00:54:308010
8011 SSLSocketDataProvider ssl(true, OK);
8012 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8013 ssl.next_proto = "spdy/2";
8014 ssl.was_npn_negotiated = true;
8015
[email protected]2d6728692011-03-12 01:39:558016 MockConnect never_finishing_connect(false, ERR_IO_PENDING);
8017 StaticSocketDataProvider hanging_non_alternate_protocol_socket(
8018 NULL, 0, NULL, 0);
8019 hanging_non_alternate_protocol_socket.set_connect_data(
8020 never_finishing_connect);
8021
[email protected]f45c1ee2010-08-03 00:54:308022 session_deps.socket_factory.AddSocketDataProvider(&data_1);
[email protected]394816e92010-08-03 07:38:598023 session_deps.socket_factory.AddSocketDataProvider(data_2.get());
[email protected]f45c1ee2010-08-03 00:54:308024 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
[email protected]2d6728692011-03-12 01:39:558025 session_deps.socket_factory.AddSocketDataProvider(
8026 &hanging_non_alternate_protocol_socket);
[email protected]f45c1ee2010-08-03 00:54:308027 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8028
8029 // First round should work and provide the Alternate-Protocol state.
8030 TestCompletionCallback callback_1;
8031 scoped_ptr<HttpTransaction> trans_1(new HttpNetworkTransaction(session));
8032 int rv = trans_1->Start(&request, &callback_1, BoundNetLog());
8033 EXPECT_EQ(ERR_IO_PENDING, rv);
8034 EXPECT_EQ(OK, callback_1.WaitForResult());
8035
8036 // Second round should attempt a tunnel connect and get an auth challenge.
8037 TestCompletionCallback callback_2;
8038 scoped_ptr<HttpTransaction> trans_2(new HttpNetworkTransaction(session));
8039 rv = trans_2->Start(&request, &callback_2, BoundNetLog());
8040 EXPECT_EQ(ERR_IO_PENDING, rv);
8041 EXPECT_EQ(OK, callback_2.WaitForResult());
8042 const HttpResponseInfo* response = trans_2->GetResponseInfo();
8043 ASSERT_FALSE(response == NULL);
8044 ASSERT_FALSE(response->auth_challenge.get() == NULL);
8045
8046 // Restart with auth. Tunnel should work and response received.
8047 TestCompletionCallback callback_3;
8048 rv = trans_2->RestartWithAuth(kFoo, kBar, &callback_3);
8049 EXPECT_EQ(ERR_IO_PENDING, rv);
8050 EXPECT_EQ(OK, callback_3.WaitForResult());
8051
8052 // After all that work, these two lines (or actually, just the scheme) are
8053 // what this test is all about. Make sure it happens correctly.
8054 const GURL& request_url = auth_handler->request_url();
8055 EXPECT_EQ("https", request_url.scheme());
8056 EXPECT_EQ("www.google.com", request_url.host());
8057
[email protected]8e6441ca2010-08-19 05:56:388058 HttpStreamFactory::set_next_protos("");
8059 HttpStreamFactory::set_use_alternate_protocols(false);
8060}
8061
8062// Test that if we cancel the transaction as the connection is completing, that
8063// everything tears down correctly.
8064TEST_F(HttpNetworkTransactionTest, SimpleCancel) {
8065 // Setup everything about the connection to complete synchronously, so that
8066 // after calling HttpNetworkTransaction::Start, the only thing we're waiting
8067 // for is the callback from the HttpStreamRequest.
8068 // Then cancel the transaction.
8069 // Verify that we don't crash.
8070 MockConnect mock_connect(false, OK);
8071 MockRead data_reads[] = {
8072 MockRead(false, "HTTP/1.0 200 OK\r\n\r\n"),
8073 MockRead(false, "hello world"),
8074 MockRead(false, OK),
8075 };
8076
[email protected]8e6441ca2010-08-19 05:56:388077 HttpRequestInfo request;
8078 request.method = "GET";
8079 request.url = GURL("http://www.google.com/");
8080 request.load_flags = 0;
8081
[email protected]cb9bf6ca2011-01-28 13:15:278082 SessionDependencies session_deps;
8083 session_deps.host_resolver->set_synchronous_mode(true);
8084 scoped_ptr<HttpTransaction> trans(
8085 new HttpNetworkTransaction(CreateSession(&session_deps)));
8086
[email protected]8e6441ca2010-08-19 05:56:388087 StaticSocketDataProvider data(data_reads, arraysize(data_reads), NULL, 0);
8088 data.set_connect_data(mock_connect);
8089 session_deps.socket_factory.AddSocketDataProvider(&data);
8090
8091 TestCompletionCallback callback;
8092
8093 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8094 int rv = trans->Start(&request, &callback, log.bound());
8095 EXPECT_EQ(ERR_IO_PENDING, rv);
8096 trans.reset(); // Cancel the transaction here.
8097
8098 MessageLoop::current()->RunAllPending();
[email protected]f45c1ee2010-08-03 00:54:308099}
8100
[email protected]76a505b2010-08-25 06:23:008101// Test a basic GET request through a proxy.
8102TEST_F(HttpNetworkTransactionTest, ProxyGet) {
[email protected]81cdfcd2010-10-16 00:49:008103 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008104 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8105 session_deps.net_log = log.bound().net_log();
8106 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8107
[email protected]76a505b2010-08-25 06:23:008108 HttpRequestInfo request;
8109 request.method = "GET";
8110 request.url = GURL("http://www.google.com/");
8111
8112 MockWrite data_writes1[] = {
8113 MockWrite("GET http://www.google.com/ HTTP/1.1\r\n"
8114 "Host: www.google.com\r\n"
8115 "Proxy-Connection: keep-alive\r\n\r\n"),
8116 };
8117
8118 MockRead data_reads1[] = {
8119 MockRead("HTTP/1.1 200 OK\r\n"),
8120 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8121 MockRead("Content-Length: 100\r\n\r\n"),
8122 MockRead(false, OK),
8123 };
8124
8125 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8126 data_writes1, arraysize(data_writes1));
8127 session_deps.socket_factory.AddSocketDataProvider(&data1);
8128
8129 TestCompletionCallback callback1;
8130
[email protected]0b0bf032010-09-21 18:08:508131 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8132
[email protected]76a505b2010-08-25 06:23:008133 int rv = trans->Start(&request, &callback1, log.bound());
8134 EXPECT_EQ(ERR_IO_PENDING, rv);
8135
8136 rv = callback1.WaitForResult();
8137 EXPECT_EQ(OK, rv);
8138
8139 const HttpResponseInfo* response = trans->GetResponseInfo();
8140 ASSERT_FALSE(response == NULL);
8141
8142 EXPECT_TRUE(response->headers->IsKeepAlive());
8143 EXPECT_EQ(200, response->headers->response_code());
8144 EXPECT_EQ(100, response->headers->GetContentLength());
8145 EXPECT_TRUE(response->was_fetched_via_proxy);
8146 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8147}
8148
8149// Test a basic HTTPS GET request through a proxy.
8150TEST_F(HttpNetworkTransactionTest, ProxyTunnelGet) {
[email protected]81cdfcd2010-10-16 00:49:008151 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008152 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8153 session_deps.net_log = log.bound().net_log();
8154 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8155
[email protected]76a505b2010-08-25 06:23:008156 HttpRequestInfo request;
8157 request.method = "GET";
8158 request.url = GURL("https://www.google.com/");
8159
8160 // Since we have proxy, should try to establish tunnel.
8161 MockWrite data_writes1[] = {
8162 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8163 "Host: www.google.com\r\n"
8164 "Proxy-Connection: keep-alive\r\n\r\n"),
8165
8166 MockWrite("GET / HTTP/1.1\r\n"
8167 "Host: www.google.com\r\n"
8168 "Connection: keep-alive\r\n\r\n"),
8169 };
8170
8171 MockRead data_reads1[] = {
8172 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8173
8174 MockRead("HTTP/1.1 200 OK\r\n"),
8175 MockRead("Content-Type: text/html; charset=iso-8859-1\r\n"),
8176 MockRead("Content-Length: 100\r\n\r\n"),
8177 MockRead(false, OK),
8178 };
8179
8180 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8181 data_writes1, arraysize(data_writes1));
8182 session_deps.socket_factory.AddSocketDataProvider(&data1);
8183 SSLSocketDataProvider ssl(true, OK);
8184 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8185
8186 TestCompletionCallback callback1;
8187
[email protected]0b0bf032010-09-21 18:08:508188 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8189
[email protected]76a505b2010-08-25 06:23:008190 int rv = trans->Start(&request, &callback1, log.bound());
8191 EXPECT_EQ(ERR_IO_PENDING, rv);
8192
8193 rv = callback1.WaitForResult();
8194 EXPECT_EQ(OK, rv);
[email protected]b2fcd0e2010-12-01 15:19:408195 net::CapturingNetLog::EntryList entries;
8196 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008197 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408198 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008199 NetLog::PHASE_NONE);
8200 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408201 entries, pos,
[email protected]76a505b2010-08-25 06:23:008202 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8203 NetLog::PHASE_NONE);
8204
8205 const HttpResponseInfo* response = trans->GetResponseInfo();
8206 ASSERT_FALSE(response == NULL);
8207
8208 EXPECT_TRUE(response->headers->IsKeepAlive());
8209 EXPECT_EQ(200, response->headers->response_code());
8210 EXPECT_EQ(100, response->headers->GetContentLength());
8211 EXPECT_TRUE(HttpVersion(1, 1) == response->headers->GetHttpVersion());
8212 EXPECT_TRUE(response->was_fetched_via_proxy);
8213}
8214
8215// Test a basic HTTPS GET request through a proxy, but the server hangs up
8216// while establishing the tunnel.
8217TEST_F(HttpNetworkTransactionTest, ProxyTunnelGetHangup) {
[email protected]81cdfcd2010-10-16 00:49:008218 SessionDependencies session_deps(ProxyService::CreateFixed("myproxy:70"));
[email protected]76a505b2010-08-25 06:23:008219 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8220 session_deps.net_log = log.bound().net_log();
8221 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8222
[email protected]76a505b2010-08-25 06:23:008223 HttpRequestInfo request;
8224 request.method = "GET";
8225 request.url = GURL("https://www.google.com/");
8226
8227 // Since we have proxy, should try to establish tunnel.
8228 MockWrite data_writes1[] = {
8229 MockWrite("CONNECT www.google.com:443 HTTP/1.1\r\n"
8230 "Host: www.google.com\r\n"
8231 "Proxy-Connection: keep-alive\r\n\r\n"),
8232
8233 MockWrite("GET / HTTP/1.1\r\n"
8234 "Host: www.google.com\r\n"
8235 "Connection: keep-alive\r\n\r\n"),
8236 };
8237
8238 MockRead data_reads1[] = {
8239 MockRead(false, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
8240 MockRead("HTTP/1.1 200 Connection Established\r\n\r\n"),
8241 MockRead(true, 0, 0), // EOF
8242 };
8243
8244 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1),
8245 data_writes1, arraysize(data_writes1));
8246 session_deps.socket_factory.AddSocketDataProvider(&data1);
8247 SSLSocketDataProvider ssl(true, OK);
8248 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8249
8250 TestCompletionCallback callback1;
8251
[email protected]0b0bf032010-09-21 18:08:508252 scoped_ptr<HttpTransaction> trans(new HttpNetworkTransaction(session));
8253
[email protected]76a505b2010-08-25 06:23:008254 int rv = trans->Start(&request, &callback1, log.bound());
8255 EXPECT_EQ(ERR_IO_PENDING, rv);
8256
8257 rv = callback1.WaitForResult();
8258 EXPECT_EQ(ERR_EMPTY_RESPONSE, rv);
[email protected]b2fcd0e2010-12-01 15:19:408259 net::CapturingNetLog::EntryList entries;
8260 log.GetEntries(&entries);
[email protected]76a505b2010-08-25 06:23:008261 size_t pos = ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408262 entries, 0, NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
[email protected]76a505b2010-08-25 06:23:008263 NetLog::PHASE_NONE);
8264 ExpectLogContainsSomewhere(
[email protected]b2fcd0e2010-12-01 15:19:408265 entries, pos,
[email protected]76a505b2010-08-25 06:23:008266 NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
8267 NetLog::PHASE_NONE);
8268}
8269
[email protected]749eefa82010-09-13 22:14:038270// Test for crbug.com/55424.
8271TEST_F(HttpNetworkTransactionTest, PreconnectWithExistingSpdySession) {
8272 SessionDependencies session_deps;
8273
8274 scoped_ptr<spdy::SpdyFrame> req(ConstructSpdyGet(
8275 "https://www.google.com", false, 1, LOWEST));
8276 MockWrite spdy_writes[] = { CreateMockWrite(*req) };
8277
8278 scoped_ptr<spdy::SpdyFrame> resp(ConstructSpdyGetSynReply(NULL, 0, 1));
8279 scoped_ptr<spdy::SpdyFrame> data(ConstructSpdyBodyFrame(1, true));
8280 MockRead spdy_reads[] = {
8281 CreateMockRead(*resp),
8282 CreateMockRead(*data),
8283 MockRead(true, 0, 0),
8284 };
8285
8286 scoped_refptr<DelayedSocketData> spdy_data(
8287 new DelayedSocketData(
8288 1, // wait for one write to finish before reading.
8289 spdy_reads, arraysize(spdy_reads),
8290 spdy_writes, arraysize(spdy_writes)));
8291 session_deps.socket_factory.AddSocketDataProvider(spdy_data);
8292
8293 SSLSocketDataProvider ssl(true, OK);
8294 ssl.next_proto_status = SSLClientSocket::kNextProtoNegotiated;
8295 ssl.next_proto = "spdy/2";
8296 ssl.was_npn_negotiated = true;
8297 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl);
8298
8299 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8300
8301 // Set up an initial SpdySession in the pool to reuse.
[email protected]02b0c342010-09-25 21:09:388302 HostPortPair host_port_pair("www.google.com", 443);
8303 HostPortProxyPair pair(host_port_pair, ProxyServer::Direct());
[email protected]749eefa82010-09-13 22:14:038304 scoped_refptr<SpdySession> spdy_session =
[email protected]102e27c2011-02-23 01:01:318305 session->spdy_session_pool()->Get(pair, BoundNetLog());
[email protected]ab739042011-04-07 15:22:288306 scoped_refptr<TransportSocketParams> transport_params(
8307 new TransportSocketParams(host_port_pair, MEDIUM, GURL(), false, false));
[email protected]02b0c342010-09-25 21:09:388308 TestCompletionCallback callback;
8309
8310 scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
8311 EXPECT_EQ(ERR_IO_PENDING,
[email protected]ab739042011-04-07 15:22:288312 connection->Init(host_port_pair.ToString(), transport_params,
8313 LOWEST, &callback,
8314 session->transport_socket_pool(), BoundNetLog()));
[email protected]02b0c342010-09-25 21:09:388315 EXPECT_EQ(OK, callback.WaitForResult());
8316 spdy_session->InitializeWithSocket(connection.release(), false, OK);
[email protected]749eefa82010-09-13 22:14:038317
8318 HttpRequestInfo request;
8319 request.method = "GET";
8320 request.url = GURL("https://www.google.com/");
8321 request.load_flags = 0;
8322
8323 // This is the important line that marks this as a preconnect.
8324 request.motivation = HttpRequestInfo::PRECONNECT_MOTIVATED;
8325
8326 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8327
[email protected]749eefa82010-09-13 22:14:038328 int rv = trans->Start(&request, &callback, BoundNetLog());
8329 EXPECT_EQ(ERR_IO_PENDING, rv);
8330 EXPECT_EQ(OK, callback.WaitForResult());
8331}
8332
[email protected]73b8dd222010-11-11 19:55:248333// Given a net error, cause that error to be returned from the first Write()
8334// call and verify that the HttpTransaction fails with that error.
8335static void CheckErrorIsPassedBack(int error, bool async) {
[email protected]cb9bf6ca2011-01-28 13:15:278336 net::HttpRequestInfo request_info;
8337 request_info.url = GURL("https://www.example.com/");
8338 request_info.method = "GET";
8339 request_info.load_flags = net::LOAD_NORMAL;
8340
[email protected]73b8dd222010-11-11 19:55:248341 SessionDependencies session_deps;
8342
8343 SSLSocketDataProvider ssl_data(async, OK);
8344 net::MockWrite data_writes[] = {
8345 net::MockWrite(async, error),
8346 };
8347 net::StaticSocketDataProvider data(NULL, 0,
8348 data_writes, arraysize(data_writes));
8349 session_deps.socket_factory.AddSocketDataProvider(&data);
8350 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data);
8351
8352 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8353 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8354
[email protected]73b8dd222010-11-11 19:55:248355 TestCompletionCallback callback;
8356 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8357 if (rv == net::ERR_IO_PENDING)
8358 rv = callback.WaitForResult();
8359 ASSERT_EQ(error, rv);
8360}
8361
8362TEST_F(HttpNetworkTransactionTest, SSLWriteCertError) {
8363 // Just check a grab bag of cert errors.
8364 static const int kErrors[] = {
8365 ERR_CERT_COMMON_NAME_INVALID,
8366 ERR_CERT_AUTHORITY_INVALID,
8367 ERR_CERT_DATE_INVALID,
8368 };
8369 for (size_t i = 0; i < arraysize(kErrors); i++) {
8370 CheckErrorIsPassedBack(kErrors[i], false /* not async */);
8371 CheckErrorIsPassedBack(kErrors[i], true /* async */);
8372 }
8373}
8374
[email protected]bd0b6772011-01-11 19:59:308375// Ensure that a client certificate is removed from the SSL client auth
8376// cache when:
8377// 1) No proxy is involved.
8378// 2) TLS False Start is disabled.
8379// 3) The initial TLS handshake requests a client certificate.
8380// 4) The client supplies an invalid/unacceptable certificate.
8381TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_NoFalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278382 net::HttpRequestInfo request_info;
8383 request_info.url = GURL("https://www.example.com/");
8384 request_info.method = "GET";
8385 request_info.load_flags = net::LOAD_NORMAL;
8386
[email protected]bd0b6772011-01-11 19:59:308387 SessionDependencies session_deps;
8388
8389 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8390 cert_request->host_and_port = "www.example.com:443";
8391
8392 // [ssl_]data1 contains the data for the first SSL handshake. When a
8393 // CertificateRequest is received for the first time, the handshake will
8394 // be aborted to allow the caller to provide a certificate.
8395 SSLSocketDataProvider ssl_data1(true /* async */,
8396 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8397 ssl_data1.cert_request_info = cert_request.get();
8398 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8399 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8400 session_deps.socket_factory.AddSocketDataProvider(&data1);
8401
8402 // [ssl_]data2 contains the data for the second SSL handshake. When TLS
8403 // False Start is not being used, the result of the SSL handshake will be
8404 // returned as part of the SSLClientSocket::Connect() call. This test
8405 // matches the result of a server sending a handshake_failure alert,
8406 // rather than a Finished message, because it requires a client
8407 // certificate and none was supplied.
8408 SSLSocketDataProvider ssl_data2(true /* async */,
8409 net::ERR_SSL_PROTOCOL_ERROR);
8410 ssl_data2.cert_request_info = cert_request.get();
8411 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8412 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8413 session_deps.socket_factory.AddSocketDataProvider(&data2);
8414
8415 // [ssl_]data3 contains the data for the third SSL handshake. When a
8416 // connection to a server fails during an SSL handshake,
8417 // HttpNetworkTransaction will attempt to fallback to SSLv3 if the initial
8418 // connection was attempted with TLSv1. This is transparent to the caller
8419 // of the HttpNetworkTransaction. Because this test failure is due to
8420 // requiring a client certificate, this fallback handshake should also
8421 // fail.
8422 SSLSocketDataProvider ssl_data3(true /* async */,
8423 net::ERR_SSL_PROTOCOL_ERROR);
8424 ssl_data3.cert_request_info = cert_request.get();
8425 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8426 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8427 session_deps.socket_factory.AddSocketDataProvider(&data3);
8428
8429 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8430 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8431
[email protected]bd0b6772011-01-11 19:59:308432 // Begin the SSL handshake with the peer. This consumes ssl_data1.
8433 TestCompletionCallback callback;
8434 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8435 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8436
8437 // Complete the SSL handshake, which should abort due to requiring a
8438 // client certificate.
8439 rv = callback.WaitForResult();
8440 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8441
8442 // Indicate that no certificate should be supplied. From the perspective
8443 // of SSLClientCertCache, NULL is just as meaningful as a real
8444 // certificate, so this is the same as supply a
8445 // legitimate-but-unacceptable certificate.
8446 rv = trans->RestartWithCertificate(NULL, &callback);
8447 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8448
8449 // Ensure the certificate was added to the client auth cache before
8450 // allowing the connection to continue restarting.
8451 scoped_refptr<X509Certificate> client_cert;
8452 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8453 &client_cert));
8454 ASSERT_EQ(NULL, client_cert.get());
8455
8456 // Restart the handshake. This will consume ssl_data2, which fails, and
8457 // then consume ssl_data3, which should also fail. The result code is
8458 // checked against what ssl_data3 should return.
8459 rv = callback.WaitForResult();
8460 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8461
8462 // Ensure that the client certificate is removed from the cache on a
8463 // handshake failure.
8464 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8465 &client_cert));
8466}
8467
8468// Ensure that a client certificate is removed from the SSL client auth
8469// cache when:
8470// 1) No proxy is involved.
8471// 2) TLS False Start is enabled.
8472// 3) The initial TLS handshake requests a client certificate.
8473// 4) The client supplies an invalid/unacceptable certificate.
8474TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Direct_FalseStart) {
[email protected]cb9bf6ca2011-01-28 13:15:278475 net::HttpRequestInfo request_info;
8476 request_info.url = GURL("https://www.example.com/");
8477 request_info.method = "GET";
8478 request_info.load_flags = net::LOAD_NORMAL;
8479
[email protected]bd0b6772011-01-11 19:59:308480 SessionDependencies session_deps;
8481
8482 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8483 cert_request->host_and_port = "www.example.com:443";
8484
8485 // When TLS False Start is used, SSLClientSocket::Connect() calls will
8486 // return successfully after reading up to the peer's Certificate message.
8487 // This is to allow the caller to call SSLClientSocket::Write(), which can
8488 // enqueue application data to be sent in the same packet as the
8489 // ChangeCipherSpec and Finished messages.
8490 // The actual handshake will be finished when SSLClientSocket::Read() is
8491 // called, which expects to process the peer's ChangeCipherSpec and
8492 // Finished messages. If there was an error negotiating with the peer,
8493 // such as due to the peer requiring a client certificate when none was
8494 // supplied, the alert sent by the peer won't be processed until Read() is
8495 // called.
8496
8497 // Like the non-False Start case, when a client certificate is requested by
8498 // the peer, the handshake is aborted during the Connect() call.
8499 // [ssl_]data1 represents the initial SSL handshake with the peer.
8500 SSLSocketDataProvider ssl_data1(true /* async */,
8501 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8502 ssl_data1.cert_request_info = cert_request.get();
8503 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8504 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8505 session_deps.socket_factory.AddSocketDataProvider(&data1);
8506
8507 // When a client certificate is supplied, Connect() will not be aborted
8508 // when the peer requests the certificate. Instead, the handshake will
8509 // artificially succeed, allowing the caller to write the HTTP request to
8510 // the socket. The handshake messages are not processed until Read() is
8511 // called, which then detects that the handshake was aborted, due to the
8512 // peer sending a handshake_failure because it requires a client
8513 // certificate.
8514 SSLSocketDataProvider ssl_data2(true /* async */, net::OK);
8515 ssl_data2.cert_request_info = cert_request.get();
8516 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8517 net::MockRead data2_reads[] = {
8518 net::MockRead(true /* async */, net::ERR_SSL_PROTOCOL_ERROR),
8519 };
8520 net::StaticSocketDataProvider data2(
8521 data2_reads, arraysize(data2_reads), NULL, 0);
8522 session_deps.socket_factory.AddSocketDataProvider(&data2);
8523
8524 // As described in ClientAuthCertCache_Direct_NoFalseStart, [ssl_]data3 is
8525 // the data for the SSL handshake once the TLSv1 connection falls back to
8526 // SSLv3. It has the same behaviour as [ssl_]data2.
8527 SSLSocketDataProvider ssl_data3(true /* async */, net::OK);
8528 ssl_data3.cert_request_info = cert_request.get();
8529 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8530 net::StaticSocketDataProvider data3(
8531 data2_reads, arraysize(data2_reads), NULL, 0);
8532 session_deps.socket_factory.AddSocketDataProvider(&data3);
8533
8534 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8535 scoped_ptr<HttpNetworkTransaction> trans(new HttpNetworkTransaction(session));
8536
[email protected]bd0b6772011-01-11 19:59:308537 // Begin the initial SSL handshake.
8538 TestCompletionCallback callback;
8539 int rv = trans->Start(&request_info, &callback, net::BoundNetLog());
8540 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8541
8542 // Complete the SSL handshake, which should abort due to requiring a
8543 // client certificate.
8544 rv = callback.WaitForResult();
8545 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8546
8547 // Indicate that no certificate should be supplied. From the perspective
8548 // of SSLClientCertCache, NULL is just as meaningful as a real
8549 // certificate, so this is the same as supply a
8550 // legitimate-but-unacceptable certificate.
8551 rv = trans->RestartWithCertificate(NULL, &callback);
8552 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8553
8554 // Ensure the certificate was added to the client auth cache before
8555 // allowing the connection to continue restarting.
8556 scoped_refptr<X509Certificate> client_cert;
8557 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8558 &client_cert));
8559 ASSERT_EQ(NULL, client_cert.get());
8560
8561
8562 // Restart the handshake. This will consume ssl_data2, which fails, and
8563 // then consume ssl_data3, which should also fail. The result code is
8564 // checked against what ssl_data3 should return.
8565 rv = callback.WaitForResult();
8566 ASSERT_EQ(net::ERR_SSL_PROTOCOL_ERROR, rv);
8567
8568 // Ensure that the client certificate is removed from the cache on a
8569 // handshake failure.
8570 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8571 &client_cert));
8572}
8573
[email protected]8c405132011-01-11 22:03:188574// Ensure that a client certificate is removed from the SSL client auth
8575// cache when:
8576// 1) An HTTPS proxy is involved.
8577// 3) The HTTPS proxy requests a client certificate.
8578// 4) The client supplies an invalid/unacceptable certificate for the
8579// proxy.
8580// The test is repeated twice, first for connecting to an HTTPS endpoint,
8581// then for connecting to an HTTP endpoint.
8582TEST_F(HttpNetworkTransactionTest, ClientAuthCertCache_Proxy_Fail) {
8583 SessionDependencies session_deps(
8584 ProxyService::CreateFixed("https://proxy:70"));
8585 CapturingBoundNetLog log(CapturingNetLog::kUnbounded);
8586 session_deps.net_log = log.bound().net_log();
8587
8588 scoped_refptr<SSLCertRequestInfo> cert_request(new SSLCertRequestInfo());
8589 cert_request->host_and_port = "proxy:70";
8590
8591 // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of
8592 // [ssl_]data[1-3]. Rather than represending the endpoint
8593 // (www.example.com:443), they represent failures with the HTTPS proxy
8594 // (proxy:70).
8595 SSLSocketDataProvider ssl_data1(true /* async */,
8596 net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
8597 ssl_data1.cert_request_info = cert_request.get();
8598 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data1);
8599 net::StaticSocketDataProvider data1(NULL, 0, NULL, 0);
8600 session_deps.socket_factory.AddSocketDataProvider(&data1);
8601
8602 SSLSocketDataProvider ssl_data2(true /* async */,
8603 net::ERR_SSL_PROTOCOL_ERROR);
8604 ssl_data2.cert_request_info = cert_request.get();
8605 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data2);
8606 net::StaticSocketDataProvider data2(NULL, 0, NULL, 0);
8607 session_deps.socket_factory.AddSocketDataProvider(&data2);
8608
8609 SSLSocketDataProvider ssl_data3(true /* async */,
8610 net::ERR_SSL_PROTOCOL_ERROR);
8611 ssl_data3.cert_request_info = cert_request.get();
8612 session_deps.socket_factory.AddSSLSocketDataProvider(&ssl_data3);
8613 net::StaticSocketDataProvider data3(NULL, 0, NULL, 0);
8614 session_deps.socket_factory.AddSocketDataProvider(&data3);
8615
8616 net::HttpRequestInfo requests[2];
8617 requests[0].url = GURL("https://www.example.com/");
8618 requests[0].method = "GET";
8619 requests[0].load_flags = net::LOAD_NORMAL;
8620
8621 requests[1].url = GURL("http://www.example.com/");
8622 requests[1].method = "GET";
8623 requests[1].load_flags = net::LOAD_NORMAL;
8624
8625 for (size_t i = 0; i < arraysize(requests); ++i) {
8626 session_deps.socket_factory.ResetNextMockIndexes();
8627 scoped_refptr<HttpNetworkSession> session(CreateSession(&session_deps));
8628 scoped_ptr<HttpNetworkTransaction> trans(
8629 new HttpNetworkTransaction(session));
8630
8631 // Begin the SSL handshake with the proxy.
8632 TestCompletionCallback callback;
8633 int rv = trans->Start(&requests[i], &callback, net::BoundNetLog());
8634 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8635
8636 // Complete the SSL handshake, which should abort due to requiring a
8637 // client certificate.
8638 rv = callback.WaitForResult();
8639 ASSERT_EQ(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED, rv);
8640
8641 // Indicate that no certificate should be supplied. From the perspective
8642 // of SSLClientCertCache, NULL is just as meaningful as a real
8643 // certificate, so this is the same as supply a
8644 // legitimate-but-unacceptable certificate.
8645 rv = trans->RestartWithCertificate(NULL, &callback);
8646 ASSERT_EQ(net::ERR_IO_PENDING, rv);
8647
8648 // Ensure the certificate was added to the client auth cache before
8649 // allowing the connection to continue restarting.
8650 scoped_refptr<X509Certificate> client_cert;
8651 ASSERT_TRUE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8652 &client_cert));
8653 ASSERT_EQ(NULL, client_cert.get());
8654 // Ensure the certificate was NOT cached for the endpoint. This only
8655 // applies to HTTPS requests, but is fine to check for HTTP requests.
8656 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8657 &client_cert));
8658
8659 // Restart the handshake. This will consume ssl_data2, which fails, and
8660 // then consume ssl_data3, which should also fail. The result code is
8661 // checked against what ssl_data3 should return.
8662 rv = callback.WaitForResult();
8663 ASSERT_EQ(net::ERR_PROXY_CONNECTION_FAILED, rv);
8664
8665 // Now that the new handshake has failed, ensure that the client
8666 // certificate was removed from the client auth cache.
8667 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("proxy:70",
8668 &client_cert));
8669 ASSERT_FALSE(session->ssl_client_auth_cache()->Lookup("www.example.com:443",
8670 &client_cert));
8671 }
8672}
8673
[email protected]89ceba9a2009-03-21 03:46:068674} // namespace net